Vous êtes sur la page 1sur 611

AVR-Assembler-Tutorial

AVR- To my private Homepage

Assembler-
Tutorial
Learning AVR Assembler with
practical examples Zu meiner privaten
Erlernen der AVR- Homepage
Assemblersprache mit praktischen
Beispielen
Want to learn how to program AT90S AVR processors in assembler language? This is the page for
you!
Wollten Sie schon immer Assemblersprache von AT90S AVR-Prozessoren erlernen? Das ist die
Seite zum Lernen!
Select your language
Goto to the english page Zur deutschen Seite
Sitemap with all pages at this site Sitemap mit allen Seiten auf dieser Webseite
Send feedback/questions to the author Feedback/Fragen an den Autor senden
Leave a new note in my guestbook Neuer Eintrag in mein Gästebuch
Visit my forum, enter a new message In das Forum gehen, einen neuen Eintrag schreiben
Besuchen Sie die Download-Seite um eine Kopie
Visit the Download page for a zipped copy
dieser Webseite down zu loaden oder den
of this webpage or the beginner's course in
kompletten Anfängerkurs in einem einzigen PDF-
one PDF doc.
Dokument.
Have a look at this webpage's visitor statistic Riskieren Sie einen Blick auf die Serverstatistik
and see how popular this page is! dieser Seite!
Inform me about any relevant changes on the Ich möchte über alle wesentlichen Änderungen auf
website by EMail dieser Webseite informiert werden.

AVR-Webring - More webpages on AVR - Weitere AVR-Webseiten


[ Join Now | Ring Hub | Random | << Prev | Next >> ]

Visitors on this page since 01.12.2001:

©2001-2008 by Gerhard Schmidt, Huegelstrasse1, D-64319 Pfungstadt/Germany


You may send me emails to info !at! avr-asm-tutorial.net (remove ! and blanks).
You may use the information on these pages and distribute it, but keep the copyright information with it.

http://www.avr-asm-tutorial.net/1/20/2009 7:28:38 PM
AVR-Tutorial

Path: Home => AVR-Overview

Tutorial for learning assembly language for the


AVR-Single-Chip-Processors
(AT90S, ATmega and ATtiny) from ATMEL with practical examples.

The Single-Chip-processors of ATMEL are excellent for homebrewing every kind of processor-
driven electronics. The only problem is that assembly has to be learned in order to program these
devices. After having done these first steps the assembly language provides very fast, lean and
effective code, by which every task can be accomodated. These pages are for beginners and help in
learning the first steps.

Sitemap New on this webpage Error list avr-source AVR-Webring

Index

Four simple programming


Beginner's introduction to AVR examples with extended comments
assembler language. Also available as first steps of a practical
as complete PDF-document for introduction to assembler
printing the whole course programming: Sense and
(Download, 1.1 MB) requirements, Simple programming
examples
For convenient operation of the
command-line assembler: a window
A command line assembler with caller including editing the source
extended error checking and and include files, viewing the list
commenting, free for download file, finding errors and editing
erroneous lines, etc., for free
download here
Binary multiplication, division, Programming and testing of the
conversion of number formats and hardware of the STK200-Board:
fixed decimals in detail, hardware EEPROM, external RAM, LCD-
multiplication display, SIO-interface
Connecting a two-line-LCD with a Converting an analog voltage to
four-line connection to the STK500 digital using the STK500 board, the
programming board with base on-board analog comparator and
routines for driving the LCD and a timer/counter 1 as pulse width
small clock application generator
Converting a digital value to an
Connectinga 4*3 keypad to an AVR analog voltage using a buffered
and sensing using Port connections R/2R network, including wave
or with a resistor matrix and an AD generation like sawtooth, triangle,
converter sinewave forms and a small tone
player application.
Small applications: a DCF77
synchronized clock, a PCM-to-
PWG-decoder, a terminal-
Software-Know-How, special
controlled frequency generator, a
assembler commands: LPM, stack
digital signal generator with
jumps, macros
frequency/pulse-width adjust and
LCD, an eggtimer as a gift, a
steppermotor controller/driver
The whole webpage for download,
ca. 2.9 MB packed, ca. 3.9 MB
Accu loader applying an ATmega16 unpacked. After download unzip
this file in a separate directory,
keeping the pathes.

Top of that page Index Error list avr-source AVR-Webring

New on this webpage

since: Description and link Source code


10.01.2009 Frequency counter with ATmega8, nine modes, LCD, 16 MHz xtal fcountV03
28.12.2008 Updated version of the beginner course in one pdf document -
New version 2.2 of the command line assembler gavrasm (free
23.12.2008 Assembler for Linux, Dos and Win, in german, englisch and french -
for 115 AVR device types)
28.09.2008 Added 16-by-24-bit hardware multiplication -
20.01.2008 Hardware multiplication with ATmega -
28.06.2007 Steppermotor controller/driver with an ATtiny13 stepper.asm
New version 2.1 of the command line assembler gavrasm (free
02.12.2006 -
Assembler for Linux, Dos and Win)
05.11.2006 An eggtimer with a ATtiny2313 as a gift eggtimer.asm
New version 2.0 of the command line assembler gavrasm (free
29.09.2006 -
Assembler for Linux, Dos and Win)
New version 1.9 of the command line assembler gavrasm (free
13.08.2006 -
Assembler for Linux, Dos and Win)
New version 1.8 of the command line assembler gavrasm (free
16.07.2006 Assembler for Linux, Dos and Win) -
Persian version of the beginner's course on the new Download page
Zipped
25.05.2006 An adjustable digital signal generator with LCD
sources
New version 1.7 of gavrasm (free AVR assembler for download).
04.05.2006 -
Corrects a bug in the ELIF directive.
17.04.2006 Added a sitemap of the whole site -
17.04.2006 Page on connecting a 4*3 keypad to an AVR -
New version 1.6 of gavrasm (free AVR assembler for download).
28.12.2005 -
Adds support for new CAN-, Tiny- and one new Mega-Type.
New version 1.5 of gavrasm (free AVR assembler for download).
27.09.2005 -
Corrected two minor bugs.
Accu cell loader hardware and assembler software applying an akkuload.asm
28.03.2005
ATmega16 zipped
Added a description of advanced directives like conditional
28.03.2005 -
assembly and on left shift of port bits in the beginner course.
New version 1.3 of gavrasm (free AVR assembler for download).
27.03.2005 Corrected false EEPROM capacity of two ATmega and added -
support for the new types ATmega 640, 1280, 1281, 2560 and 2561.
New version 1.2 of gavrasm (free AVR assembler for download).
08.03.2005 Corrected some minor bugs and added support for the new types -
ATtiny25, 45 and 85.
New version 1.1 of gavrasm (free AVR assembler for download).
06.01.2005 Corrected some minor bugs in the MACRO treatment, finally added -
support for the historic program counter PC.
sawtooth1
sawtooth2
Applying an R/2R resistor network for Digital-to-Analog
03.01.2005 triangle
conversion and generating waveforms
sinewave and
wavetable music
New version 1.0 of gavrasm (free AVR assembler for download.
09.10.2004 Added support for ATmega325 etc., an extra error file and others. -
New version of the window caller, assimilated to gavrasm 1.0
gavrasm (Free AVR assembler) in improved version 0.9 for
28.03.2003 -
download. Added support for ATmega48/88/168 now.
gavrasm (Free AVR assembler) in improved version 0.8 for
download. Corrects some minor errors. Also, a new version of the
15.02.2004 -
convenient window caller for the command line assembler for free
download.
30.12.2003 Beginner course as complete PDF file for download available -
gavrasm (Free AVR assembler) in improved version 0.7 for
download. Corrects an error with AT90S1200, adds the new AVR
20.10.2003 -
type ATtiny2313, provides IFDEVICE directive for type-specific
code.
New version of the convenient window caller for the command line
09.09.2003 assembler, improved editor for include files, viewing the list file, -
error finder, etc. for free download here.
gavrasm (Free AVR assembler) in improved version 0.6 for
03.09.2003 download. Corrects an error with negative numbers, adds several -
AVR types, provides nested IF/ELSE/ENDIF.
Convenient window caller for the command line assembler, simple
26.08.2003 editor for the source file, viewing the list file, etc. for free download -
here.
gavrasm (Free AVR assembler) in improved version 0.5 for
16.08.2003 download. Corrects an error in the instruction set of AT90S1200 in -
previous versions.
gavrasm (Free AVR assembler) in improved version 0.4 for
21.07.2003 download. For convenient calling the assembler I have a window -
caller for free download.
gavrasm (Free AVR assembler) in improved version 0.3 for
14.06.2003 -
download.
gavrasm (Free AVR assembler) in improved version 0.2 for
31.05.2003 -
download
Analog-to-Digital-Conversion using the analog comparator and
17.05.2003 ADC8.asm
timer/counter 1 of the AT90S8515 on board a STK500
8-Bit ADC
09.05.2003 Fixed decimal point numbers
10-Bit ADC
24.12.2002 Free AVR assembler for download -
14.09.2002 Introduction to Studio Version 4 -
23.08.2002 Hardware programming equipment for the beginner -
11.08.2002 Creating tables in the program flash memory -
Connecting a 2-line-LCD to a STK500 port, with a date/time Lcd4IncE.asm
13.04.2002
software clock Lcd4IncCE.asm
All instructions and many terms in the assembler source files
(HTML format) of the example pages are now linked to the
02.02.2002 -
description in the beginner course, so you can easily have more
explanation on them.
02.02.2002 Added a page on assembler directives and expressions -
Added number format conversion tutorial and routines and
06.01.2002 restructured the calculation pages, removed several minor HTML CONVERT.asm
syntax errors.
Renewed all assembler source files: commands in lower case letters
to be more compatible with the editor from ATMEL (which still is
source
not as advanced - compared to Tan's -, let me know if you need the
03.01.2002 file
Linux FPK or Win-Delphi Pascal sources for the self-written
software if you have a similiar job to do), added a new index page index
to all source files
Binary math MULT8E.asm
16.12.2001
(multiplication and division) DIV8E.asm
Moved these pages from http://www.dg4fac.de to this new location
01.12.2001 -
at http://www.avr-asm-tutorial.net due to elevated traffic.
10.07.2001 Structure of asm source code 8515STD.asm
24.09.2001 Intro to the studio version 3.52 -
12.08.2001 Beginner's introduction to AVR assembler language -
DCF synchronised clock with serial interface in a 2313 CLOCK.asm
14.01.2001
Echoes serial characters back as hex, for the STK200 board SIOHEX.asm
Small application page -
23.12.2000 PCM to Analogue Decoder for remote control systems PCM2PWG4.asm
Terminal controlled pulse generator PWGSIO2.asm
TESTMAC1.asm
TESTMAC2.asm
09.12.2000 Examples for the use of macros in assembler language!
TESTMAC3.
asm

Top of that page Index Download avr-source AVR-Webring

Known and corrected bugs

Date File(s) Error description Status Thanks


10.01.2009 keyboard.html Error in source code for keypad corrected Carl Rheinlaender
Akkuload-Analog schematic:
26.08.2007 switch_schem.gif corrected Jonny Bijlsma
Error in wiring of channel 3
Akkuload: Caused by a serious
bug in the calculation routine, the
02.05.2005 akkucalc.asm currents are by a factor of Corrected. Sebastian Mazur
roughly two too small, and are
displayed false.
If you use gavrasm for
assembling, and if you add more
than one ORG directive within
the code, and if you use Pony-
Prog for burning the Hex- and
gavrasm and
06.01.2005 Eep-files to the AVR, the shift in Pending (Self)
Pony-Prog
adress, caused by the ORG
directive, is implemented in
INTEL-Hex-format, but ignored
by Pony-Prog. Be cautious when
using more than one directive.
False description of the BLD and
01.10.2004 CALC.html Corrected Mark
BST instruction
Lcd4IncE Bug in the LCD-Clock asm file
05.12.2003 Corrected Dan Carroll
Lcd4IncCE prevented compilation
FP_CONV10, HTML A missing code line caused Thilo
05.07.2003 Corrected
.ASM calculation errors Mölls
Corrected the pullup resistor in
the experimental circuit, due to Andreas
24.12.2002 exp2313.gif Corrected
occasional reset problems Wander
reported, to a lower value
Corrected an error in the source Jan de
24.12.2002 (several) Corrected
code for the 4-Bit-LCD software Jong
Elapsed processor time with
15.07.2002 DIVISION.html Corrected Armin Kniesel
wrong dimension
8515STD.html
16.02.2002 Two int vectors missing! Corrected -
8515std.asm
The interrupt routine has a
serious bug. The result is an
unhandled interrupt, delaying
testsint.asm
execution of the program by
sioint.asm
approx. a factor of 30. As this
31.12.2001 sioint.inc Removed (myself)
routine requires external SRAM
bcdmath.inc
and so doesn't work with
bcdmath.asm
STK500, I removed these codes
and will not provide a debugged
routine instead.
RTS and CTS between the plug
and the line driver were
exchanged. The plug is to be
clock.gif Wim
23.12.2001 connected to the PC using a Corrected
clock.pdf Korevaar
crossed link for RD/TD and RTS/
CTS. PB4 must be set to 0 to
activate the CTS line.
Download of the inc-files results
bcdmath.inc in an error message from the
Axel
25.11.2001 sioint.inc server. These files were renamed Corrected
Rühl
testsint.asm to .asm and the calling asm file
corrected.
Stefan
24.09.2001 (Several) Errors using .DEF and .EQU Corrected
Beyer
When working with a DCF77
signal the seconds are incorrect Open! -
CLOCK.html (59.th second is already 0).
CLOCK.asm
Error in the calculation of tens of Thomas
Corrected
03.06.2001 monthes from the DCF77 signals Baumann
Some minor additions and Frank
(Several) corrected
changes in the text Dalchow
TEST1.html Brian
Some translation errors in the text corrected
TEST1.asm Tangney
It was stated that the frequency of
TEST1.html Timo
02.12.2000 the LEDs is 800 kHz. In fact it is corrected
TEST1.asm Engelmann
only 667 kHz!

Top of that page Index Download avr-source Error list

AVR-Webring
The AVR webring provides hundreds of links to AVR related webpages. Please have a look at these
if you search for more informations on AVRs.

This page is member in the AVR-Webring:


AVR-Webring
[ Join Now | Ring Hub | Random | << Prev | Next >> ]

Visitors on this page since 16.12.2001:

©2002-2009 by http://www.avr-asm-tutorial.net
You may use, copy and distribute these pages as long as you keep the copyright information with it.

http://www.avr-asm-tutorial.net/avr_en/index.html1/20/2009 7:28:59 PM
AVR-Tutorial

Pfad: Home => AVR-Übersicht

Tutorial für das Erlernen der Assemblersprache von


AVR-Einchip-Prozessoren
(AT90S, ATmega, ATtiny) von ATMEL anhand geeigneter praktischer
Beispiele.

Die Einchip-Prozessoren von ATMEL eignen sich hervorragend für den Eigenbau prozessor-
gesteuerter Elektronik. Einzige Hürde ist dabei die Assembler-Sprache, mit der die vielseitigen
Winzlinge zu programmieren sind. Wenn man die ersten Hürden überwunden hat, wird man
allerdings mit den sehr schlanken, sehr schnellen und ereignisgesteuerten Programmen jeden Ablauf
in den Griff bekommen. Diese Seite wendet sich an Anfänger und hilft bei den ersten Schritten.

Sitemap Neu auf dieser Seite Fehlerhinweise asm-Sourcen AVR-Webring

Inhalt

Ausführliche allgemeine Einführung


mit allen Werkzeugen, Präsentation der AVR-
Befehlsbeschreibungen, Befehls- und Mikroprozessoren im PDF-
Porttabellen, u.v.a.m.! Format mit praktischen
Als komplette PDF-Datei (64 Seiten) Beispielen für den ATtiny13 und
zum Ausdrucken (Download ca. 856 mit Assembler-Quelltext
kB)
Vier einfache, ausführlich Das Werkzeug: ein
kommentierte Programmbeispiele, für Kommandozeilen-Assembler in
Anfänger als erste Schritte. Sinn, deutscher Sprache für DOS,
Zweck und Voraussetzungen der Win32 und Linux(i386) zum
Beispiele, vier einfache Download, mit
Programmierbeispiele zum Erlernen Fehlerkommentierung für
von Assembler Anfänger und mit vielen Extras!

Alles über Zeitschleifen, mit dem Alles über Interrupts und


beliebten Sekundenblinker Interrupt-Programmierung

Ausführliche Erklärungen und


Ein Windows-Programm zum
Routinen zu den Themen
komfortablen Aufruf des
Multiplikation, Division,
Kommandozeilen-Assemblers, zum
Zahlenumwandlung und
Editieren der Source- und Include-
Festkommazahlen in Assembler
Dateien, zum Anzeigen der Listdatei,
mit Beispielen (binär, dezimal,
zur komfortablen Fehlersuche, u.a.m.
hex, ASCII), Hardware-
zum Download
Multiplikation
Ansteuerung von Peripherie am
Beispiel des STK200: Anschluss einer 2-Zeilen-LCD an
Programmierung und Testen der das STK500 mit Basisroutinen
Hardware auf dem STK-Board: und Beispielprogramm für eine
EEPROM, externes RAM, LCD- Uhr
Display, SIO-Schnittstelle
Aufbau eines 8-Bit-AD-Wandlers mit Anschluss einer 12-er-Tastatur an
dem eingebauten Analogkomparator
einen AVR und Auslesen mittels
und dem Timer/Counter1 am STK500
Programmierboard, mit ausführlicher Portansteuerung oder mit
Beschreibung und Software in HTML- Widerstandsmatrix und einem
Form und als Assembler Quellcode AD-Wandler

Umwandlung eines Digitalwerts in


eine analoge Spannung mit einem
Software-Know-How,
gepufferten R/2R Netzwerk,
Spezialitäten einiger
einschließlich Erzeugung von
Wellenformen wie Sägezahn, Dreieck, Assemblerbefehle (LPM, Stack-
Sinus (mit Sinustabelle) und einem Sprung, Makros)
einfachen Musiknotenspieler
Sammlung von kommentierten
Anwendungen: DCF77-Uhr, PCM-
Decoder, Pulsweiten-
Rechteckgenerator mit seriellem
Interface, Rechteckgenerator mit
Potieinstellung und LCD,
Akkulader mit einem ATmega16
Frequenzzähler mit Frequenz-,
Perioden-, Periodenanteils-,
Umdrehungs- und
Spannungsmessung, Eieruhr zum
Verschenken, Schrittmotor-Steuerung,
etc.
Abdruck einer Artikelserie in der
Amateurfunkzeitschrift cq-dl des
Deutschen Amateur-Radio Club
DARC:
Gezipptes Abbild dieser Seite
herunterladen (ca. 3,8 MB) und in
● Teil I: Hardware von AVR-
ein Verzeichnis auf dem eigenen
Prozessoren
Rechner entpacken (ca. 20 MB).
● Teil II: Software von AVR-
Dabei unbedingt die
Prozessoren
Verzeichnisse des Pakets
● Teil III: Programmieren der
beibehalten!
Prozessoren
● Teil IV: Morse-Ausgabe mit
AVR-Prozessor

Seitenanfang Inhalte Fehlerhinweise asm-Sourcen AVR-Webring

Neu auf dieser Seite

seit: Beschreibung und Link Sourcecode


Verbesserte Version 3 des Frequenzzählers mit Frequenz-,
09.01.2009 Perioden-, Periodenanteil-, Umdrehungs- und fcountV03
Spannungsmessung mit ATmega8
Aktualisierte und verbesserte Version des Anfängerkurses in
07.01.2009 einem PDF-Dokument -
Update des gezippten Abbildes der Webseite
gavrasm Assembler in Version 2.2 (deutsch, englisch und
23.12.2008 -
französisch, für 115 AVR-Typen) zum kostenlosen Download
Erweiterung der Hardware-Multiplikation um 16-mit-24-Bit-
28.09.2008 -
Multiplikation
25.05.2008 Zeitschleifen, Tonausgabe mit Lautsprecher, LED-Blinker -
25.05.2008 Interrupts und Interrupt-Programmierung -
20.01.2008 Hardware-Multiplikation mit ATmega -
28.06.2007 Schrittmotor-Steuerung mit einem ATtiny13 schrittmotor_v1.asm
02.12.2006 gavrasm Assembler in Version 2.1 zum kostenlosen Download -
29.10.2006 ATtiny2313-Eieruhr eieruhr.asm
29.09.2006 gavrasm Assembler in Version 2.0 zum kostenlosen Download -
13.08.2006 gavrasm Assembler in Version 1.9 zum kostenlosen Download -
gavrasm Assembler in Version 1.8 zum kostenlosen Download
16.07.2006 Persische Version des Anfängerkurses auf der neuen Download- -
Seite.
Frequenzzähler mit Frequenz-, Perioden-, Periodenanteil-,
17.06.2006 fcountV02
Umdrehungs- und Spannungsmessung mit ATmega8
Gezippter
25.05.2006 Einstellbarer Rechteckgenerator mit Potieinstellung und LCD
Quellcode
gavrasm Assembler in Version 1.7 zum kostenlosen Download.
04.05.2006
Korrigiert einen Fehler bei der Behandlung der ELIF-Direktive.
Präsentation der AVR-Mikroprozessoren an Beispielen mit dem
15.4.2006 (diverse)
ATtiny13
Anschluss einer 12-er-Tastatur an einen AVR und Auslesen
23.2.2006 -
mittels I/O-Leitungen oder einen AD-Wandler
gavrasm Assembler in Version 1.6 zum kostenlosen Download.
28.12.2005 -
Unterstützt neue CAN, Tiny- und einen neuen Mega-Typ.
gavrasm Assembler in Version 1.5 zum kostenlosen Download.
27.9.2005 -
Beseitigt zwei kleine Fehler.
Hardware und Assembler-Software für ein Akkuladegerät für bis akkuload.asm,
28.3.2005
zu vier einzelnen Zellen gezippt
Beschreibung der fortgeschrittenen Direktiven zur bedingten
28.3.2005 Assemblierung und des Linksschiebens bei Portbit-Angaben im -
Anfängerkurs
gavrasm Assembler in Version 1.3 zum kostenlosen Download.
Beseitigt eine falsche Angabe der EEPROM-Größe bei zwei
27.3.2005 -
ATmega-Typen und implementiert die neuen ATmega 640, 1280,
1281, 2560 und 2561.
gavrasm Assembler in Version 1.2 zum kostenlosen Download.
8.3.2005 Beseitigt einige kleine Fehler und implementiert die neuen AVR- -
Typen ATtiny25, 45 und 85.
gavrasm Assembler in Version 1.1 zum kostenlosen Download.
6.1.2005 Beseitigt einige kleine Fehler und implementiert die Verwendung -
des Programmcounters PC.
Sägezahn1
Sägezahn2
R/2R-Widerstandsnetzwerk als Digital-zu-Analog-Wandler, mit
4.1.2005 Sinus
einigen einfachen Anwendungen
Sinus-Tabelle
Musik
gavrasm Version 1.0 mit einem kleinen Fix
9.10.2004 Neue Version des Windows-Helfers zum Assemblieren, an -
Version 1.0 von gavrasm angepasst und mit deutscher Hilfe
gavrasm Assembler in Version 1.0 zum kostenlosen Download.
Unterstützt die neuen Typen ATmega325/3250/645/6450, viele
3.10.2004 -
neue Direktiven und erzeugt eine zusätzliche Datei mit allen
Fehlermeldungen.
gavrasm Assembler in Version 0.9 zum kostenlosen Download.
28.03.2004 -
Unterstützt die neuen Typen ATmega48/88/168.
gavrasm Assembler in Version 0.8 zum kostenlosen Download
mit kleinen Korrekturen. Außerdem eine neue Version des
15.02.2004 -
Window Callers zum komfortablen Umgang mit dem
Kommandozeilen-Assembler zum kostenlosen Download
Anfängerkurs als komplette Datei im PDF-Format (Download,
30.11.2003 -
(78 Seiten, 850 kB)).
gavrasm Assembler in Version 0.7 zum kostenlosen Download.
Korrigiert einen Fehler beim AT90S1200, unterstützt jetzt auch
20.10.2003 -
den neuen Typ ATtiny2313, IFDEVICE-Direktive für typ-
spezifischen Code.
Eine neue Version des Window Callers zum komfortablen
09.09.2003 Umgang mit dem Kommandozeilen-Assembler zum kostenlosen -
Download
gavrasm Assembler in Version 0.6 zum kostenlosen Download.
03.09.2003 Korrigiert einen Fehler beim Rechnen mit negativen Zahlen, -
unterstützt mehr AVR-Typen, verschachtelte IF/ELSE/ENDIF.
Ein Window Caller zum komfortablen Umgang mit dem
26.08.2003 -
Kommandozeilen-Assembler zum kostenlosen Download
gavrasm Assembler in Version 0.5 zum kostenlosen Download.
16.08.2003 -
Korrigiert einen Fehler im Instruktionsset von AT90S1200.
gavrasm Assembler in Version 0.4 zum kostenlosen Download.
21.07.2003 Ein Windows- Caller zur Vereinfachung des Aufrufs steht -
ebenfalls zum kostenlosen Download.
14.06.2003 gavrasm Assembler in Version 0.3 zum kostenlosen Download. -
gavrasm (freier AVR Assembler) in Version 0.2 zum kostenlosen
31.05.2003 -
Download.
17.05.2003 8-Bit-AD-Wandler am STK500 Board adc8.asm
8-Bit-ADC
09.05.2003 Rechnen mit Festkommazahlen
10-Bit-ADC
Endlich fertig, der Assembler für den Anfänger: zum kostenlosen
24.12.2002 -
Download.
14.09.2002 Einführung in den Umgang mit dem Simulator Studio 4 -
Einfache Hardware zum Programmieren und Experimentieren für
20.08.2002 -
den Anfänger
11.08.2002 Erstellen von Tabellen im Programm-Flash-Speicher -
Ansteuerung einer 2-Zeilen-LCD-Anzeige mit dem STK500- Lcd4Inc.asm
11.04.2002
board mit Uhrprogramm Lcd4IncC.asm
Alle Befehle und Stichwörter der Assembler-Quelltexte in
02.02.2002 HTML bei den Beispielen sind jetzt mit den Erläuterungen im -
Beginner-Kurs verlinkt.
02.02.2002 Liste aller Assemblerdirektiven und Ausdrücke -
Routinen zur Zahlenumwandlung Dezimal, BCD, Binär und
05.01.2002 konvert.asm
Hexadezimal
In allen Quellcode-Dateien wurden Assembler-Instruktionen jetzt
in Kleinschreibung umgewandelt, weil der Editor von ATMEL
noch immer keine grossbuchstabigen Instruktionen erkennt (ist Index
nicht so schlau wie der von Tan, wer die selbst geschriebene
03.01.2002 aller
Software in Linux FPK Pascal oder Win-Delphi braucht, um eine
ähnliche Ochsentour zu vermeiden, melde sich bei mir). Quelldateien
Außerdem gibt es jetzt eine Index-Seite mit Links zu allen
Quelldateien.
Grundrechenarten in Assembler mult8.asm
16.12.2001
(Multiplikation und Division) div8d.asm
Umzug dieser Seiten von http://www.dg4fac.de nach hier: http://
1.12.2001 -
www.avr-asm-tutorial.net, bedingt durch sehr viel Webverkehr.
7.10.2001 Struktur eines Assemblerprogrammes mit Vorlage für den 8515 8515std.asm
24.9.2001 Einführung in die Studio Version 3.52 -
10.6.2001 Werkzeuge zur Assemblerprogrammierung -
25.2.2001 Allgemeine Einführung -
DCF77-synchronisierbare Uhr mit serieller Schnittstelle im 2313 dcf77uhr.asm
14.01.2001 SIO-Testprogramm mit Hexadezimalcode-Echo für STK200
siohex.asm
Board
Kleine Anwendungsseite -
23.12.2000 PCM zu Analog Decoder für Fernsteuerungen pcm2pwg4.asm
SIO-gesteuerter Rechteck-Signalgenerator pwgsio2.asm
testmac1.asm
09.12.2000 Beispiele für die Anwendung von Makros in Assembler! testmac2.asm
testmac3.asm

Seitenanfang Inhalte AVR-Webring

Bekannte und korrigierte Fehler:

Datum Datei(en) Fehlerbeschreibung Status Dank


Fehler beim Auslesen der
09.01.2009 HTML-Seite Zehnertastatur über einen korrigiert Carl Rheinländer
Portanschluss
Beschreibung Fehler bei der Autorange-
in v3
09.01.2009 Quellcode Implementierung im Frequenzzähler -
korrigiert
html-listing mit ATmega8
Akkulader-Analogteil: Fehler im
26.08.2007 switch_schem.gif Schaltbild: vertauschen AD-Wandler- korrigiert Jonny Bijlsma
Anschlüsse bei Kanal 3
Akkuload: Fehler in der Umrechnung
gemessener Spannungen in Ströme
02.02.2005 akkucalc.asm korrigiert Sebastian Mazur
führt zu halbem Ladestrom und
falscher Anzeige
Wird gavrasm zum Assemblieren
verwendet und darin eine weitere,
zweite ORG-Direktive ausgeführt,
anschließend mit Pony-Prog die Hex-
gavrasm mit und Eep-Datei eingelesen, dann
06.01.2005 offen (selbst)
Pony-Prog wertet Pony-Prog die geänderte
Adresse im Intel-Hex-Format nicht
korrekt aus, Pony-Prog ignoriert das
ORG. Vorsicht bei der Verwendung
solcher Konstruktionen!

fp_conv10, HTML Fehler bei der 10-bit-AD-Wandler- Thilo


05.07.2003 Umrechnung in 4-digit-Fließomma, Korrigiert
fp_conv_10, ASM Mölls
verursachte Rechenfehler
Pullup-Widerstand in der Schaltung
Andreas
24.12.2002 exp2313.gif verkleinert, weil gelegentlich Korrigiert
Wander
Probleme beim Reset auftreten
Einige Link-Fehler im Beginner-
Tutorial (Portbeschreibungen) sowie Jan de
24.12.2002 (diverse) Korrigiert
einen Fehler im Uhrenquellcode der 4- Jong
Bit-LCD-Steuerung beseitigt
Fehler bei der Angabe der
15.07.2002 division.html Behoben Armin Kniesel
Prozessorzeit
Fehler bei der Beschreibung der
29.04.2002 test2.html Behoben Ralf Schumnig
Datenrichtungsregister
8515std.html
16.02.2002 Zwei Interrupt-Vektoren fehlten! Korrigiert -
8515std.asm
13.01.2002 (alle) Zahlreiche HTML-Syntaxfehler Korrigiert -
Die Interrupt-Service-Routine enthält
einen schweren Bug, der zu dauerhaft
unbehandelten Interrupts des UARTs
testsint.asm
führt, die die weitere Bearbeitung um
sioint.asm
etwa den Faktor 30 verlangsamt! Da (Selber
31.12.2001 sioint.inc Entfernt
die Routinen externes SRAM gemerkt)
bcdmath.inc
erfordern und deshalb ohnehin nicht
bcdmath.asm
mit dem STK500 zusammen spielen,
werde ich vorerst keine ausgebesserte
Version dafür schreiben.
RTS und CTS Verbindung zwischen
dem 9-poligen Stecker und dem
Pegelwandler ist vertauscht
eingezeichnet. Die Anschlsse sind mit
clock.gif Wim
23.12.2001 einem gekreuzten Anschlusskabel Korrigiert
clock.pdf Korevaar
(RD/TD, RTS/CTS) mit dem PC zu
verbinden. Portbit PB4 muss auf 0
gesetzt werden, damit CTS aktiviert
wird!
Die beiden inc-Dateien lassen sich
bcdmath.inc nicht von der Webseite laden. Die
Axel
25.11.2001 sioint.inc Dateien wurden in .asm umbenannt Korrigiert
Rühl
testsint.asm und die aufrufende Quelldatei
korrigiert.
Falsche Verwendung von .DEF und . Stefan
24.9.2001 (Diverse) Korrigiert
EQU Instruktionen Beyer
1. Falsche Verwendung des LDI-
Befehls für R1
sprung.html Korrigiert caswi
2. Falsche Angabe der Verzögerung
bei Delay10
Bei DCF77-Empfang falsche Ausgabe
03.06.2001 Offen! -
dcf77uhr.html der Sekunden (59. ist bereits 0)
dcf77uhr.asm Fehlerhafte Berechnung der Thomas
Korrigiert
Monatszehner aus dem DCF77-Signal Baumann
Kleinere Fehler und Ergänzungen im Frank
(Diverse) Korrigiert
Text Dalchow
Es wurde behauptet, die
test1.html Blinkfrequenz der LEDs betrüge Timo
02.12.2000 Korrigiert
test1.asm 800 kHz. Tatsächlich sind es nur Engelmann
667 kHz.

Seitenanfang Inhalte asm-Sourcen Fehlerhinweise

AVR-Webring
Im AVR-Webring sind hunderte Webseiten versammelt, die sich mit den AVR befassen.

Diese Seite ist Mitglied im AVR-Webring:


AVR-Webring
[ Mitglied werden | Ring Hub | Zufallsauswahl | Vorheriger | Nächster ]

Besucher auf dieser Seite seit 16.12.2001:

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/index.html1/20/2009 7:29:12 PM
Sitemap der Webseite http://www.avr-asm-tutorial.net

Sitemap der Webseite http://www.avr-asm-


tutorial.net in deutsch
Hauptseite
Deutsche Leitseite

● Anfänger's Einführung in AVR-Assembler


❍ Gesamter Kurs als PDF beginner_de.pdf

❍ Hardware ISP-Programmier-Interface

❍ Warum in Assembler programmieren?

❍ Werkzeuge für die AVR-Assembler-Programmierung

■ Erste Schritte mit dem Studio 4

■ Erste Schritte mit dem Studio 3.52

■ Direktiven in Assembler

■ Struktur von AVR-Assembler-Programmen

■ Standard 8515 Programm-Datei Struktur

■ Programmplanung

❍ Verwendung von Registern in Assembler

❍ Verwendung von Ports in Assembler

■ Port Details im AT90S8515

❍ Verwendung von SRAM in Assembler

❍ Relative und absolute Sprünge, Reset- und Interrupt-Vektoren

❍ Rechnen in Assembler

❍ Tabellen: Instruktionen, Abkürzungen, Ports, Vektoren, Direktiven, Ausdrücke

● Binäres Rechnen in AVR Assembler


❍ Binäres Multiplizieren zweier 8-Bit-Zahlen in AVR Assembler

❍ Assembler Quelltext der Multiplikation

❍ Division einer 16-Bit-Zahl durch eine 8-Bit-Zahl

❍ Assembler Quellcode der Division

❍ Zahlenumwandlung in AVR-Assembler

❍ Quelltext der Zahlenumwandlungsroutinen

❍ Umgang mit Festkommazahlen in AVR Assembler

❍ Assembler Quelltext der Umwandlung einer 8-Bit-Zahl in eine dreistellige

Festkommazahl
❍ Assembler Quelltext der Umwandlung einer 10-Bit-Zahl in eine vierstellige

Festkommazahl
❍ Hardware-Multiplikation mit ATmega

● Vier einfache Programmierbeispiele als erste Schritte zum Lernen


❍ Test 1: Ausgabe an die Leuchtdioden.

❍ Test 2: Eingabe von einem Port

❍ Test 3: Timer im Polling mode

❍ Test 4: Timer im Interupt mode

● Zeitschleifen
❍ 8-Bit-Zeitschleifen

■ Hardware für die Tonausgabe über Lautsprecher

❍ 16-Bit-Zeitschleifen

■ Hardware für den LED-Blinker

● Einführung in die Interrupt-Programmierung


❍ Interrupt-Vektoren

❍ Interruptquellen

❍ Programmablauf bei Interrupts

■ Grafik Ablauf von Interrupt-Programmen

■ Grafik Ablauf bei mehreren Interrupts

❍ Interrupt und Ressourcen

● AVR-Hardware-Testroutinen für einen AT90S8515 auf dem STK200


❍ Vorrausetzungen für die Beispiele

❍ Demonstriert den Gebrauch des EEPROMs

❍ TestRam testet exteres RAM auf dem STK-200 board

❍ Tested eine angeschlossene LCD-Anzeige

■ Include-Routinen zur LCD-Ansteuerung

■ Uhrenanwendung zum LCD-Test

❍ Testet die Serielle Schnittstelle auf dem Board

■ Hardware der Verbindung des Boards mit dem PC

■ SIO-Software

■ Hex-Echo über SIO

❍ Anschluss eines Keyboards an Port B

● Kleine AVR-Anwendungen
❍ DCF77 Uhr mit dem AVR-Controller AT90S2313

■ Schaltbild clock.pdf

❍ Decoder für Fernsteuersignale mit AT90S2313

■ Software für PCM-Decoder

■ aBLAUFDIAGRAMM pcm2flow.pdf

■ Schaltbild pcm2pwg4.pdf

❍ ANSI-Terminal programmierbarer Signalgenerator

■ Quellcode für den Pulsweiten-Generator

❍ Einstellbarer Rechteckgenerator mit ATmega8 und LCD-Anzeige

■ Quellcode Hauptprogramm, html

■ Quellcode LCD-Routinen, html

■ Quellcode Frequenztabelle, html

■ Quellcode alles, asm

■ Schaltbild

❍ Frequenzzähler mit ATmega8 und LCD-Anzeige

■ Quellcode Programm, html

■ Quellcode Programm, asm

■ Schaltbild Prozessorteil

■ Schaltbild Vorverstärker, Vorteiler

■ ATmega8 Fuses, Studio, Teil 1

■ ATmega8 Fuses, Studio, Teil 2

■ ATmega8 Fuses, PonyProg

❍ ATtiny2313-Eieruhr zum Verschenken

■ Quellcode, html

■ Quellcode, asm

■ Beispiel-Anleitung, Open-Office-Format

■ Beispiel-Anleitung, Rich-Text-Format

■ Schaltbild, GIF, groß

■ Schaltbild, GIF, verkleinert

❍ Steppermotorsteuerung mit ATtiny13

■ Quellcode im .asm-Format

■ Quellcode im .html-Format

■ Schaltbild Steuerung im .gif-Format

■ Schaltbild Steuerung im .pdf-Format

■ Bild der Steuerung

■ Schaltbild Netzteil im .gif-Format

■ Schaltbild Netzteil im .pdf-Format

■ Bild Netzteil

■ Bild Schrittmotor

■ Bild Steuerung und Schrittmotor, klein

● Anschluss einer 2-zeiligen LCD-Anzeige an das STK500


❍ Include-Routinen für LCD-Anzeige am STK500

❍ Uhrenanwendung für LCD-Anzeige an das STK500

● AVR-PWM-ADC für STK500


❍ Software für PWM-ADC

● R/2R-Netzwerk als DAC für einen AVR


● Spezielles Programmier-Know-How
❍ Anwendung der LPM-Instruktion

❍ JUMP über den Stack

❍ Makro-Befehl-Beispiel

❍ Sprungziele in Makros

❍ Parameter-Übergabe an Makro

● Anschluss einer 12-er-Tastatur an einen AVR


❍ Open-Office Spreadsheet

❍ Excel Spreadsheet

● Präsentation der AVR-Mikrokontroller mit Anwendungsbeispielen


❍ Teil_1_Prozessoren.pdf

❍ Teil_2_BitsAndBytes.pdf

❍ Teil_3_Befehle.pdf

❍ Teil_4_AufbauTiny13.pdf

❍ Anwendungsbeispiele.pdf

❍ Teil_5b_Beispiel01_02.pdf

❍ Teil_6_Beispiel03_07.pdf

❍ Teil_7_Beispiel08_10.pdf

❍ Teil_8_Beispiel_11.pdf

❍ Teil_5a_UebersichtBeispiele.pdf

❍ Quellcode der Beispiele:

■ bsp01_loop.asm

■ bsp02_led.asm

■ bsp03_blink.asm

■ bsp04_blink_langsam.asm

■ bsp04_blink_langsam_takte.asm

■ bsp04_blink_langsam_tn12.asm

■ bsp05_blink_Timer.asm

■ bsp05_blink_Timer_kurz.asm

■ bsp06_lsp.asm

■ bsp07_keyint.asm

■ bsp08_morsekey.asm

■ bsp09_adcmorsekey.asm

■ bsp10_morsebake.asm

■ bsp11_1750_SinePwm.asm

● AVR-Einführung für Funkamateure


❍ Teil 1: Eigenschaften von AVR-Mikrokontrollern

■ Schaltbild mit 2313

■ Anschlüsse eines 2323

❍ Teil 2: Software der Prozessoren

■ Quellcode: beispiel.asm

❍ Teil 3: Programmieren der Prozessoren

■ ISP-Interface zum Programmieren

❍ Teil 4: Beispielanwendung CW-Geber

■ Schaltbild des CW-Gebers

■ Quellcode für 2313: Cw01.asm

■ Listing für 2313: Cw01.html

■ Quellcode für STK500: Cw01_500.asm

■ Listing der Software für STK500

■ Quellcode für STK200: Cw01_200.asm

■ Listing für STK200: Cw01_200.html

● Gerd's AVR Assembler


❍ Deutsche Download-Seite

❍ LiesMich.Txt

❍ gavrasm_lin_de_22.zip

❍ gavrasm_win_de_22.zip

❍ gavrasm_dos_de_22.zip

❍ DosRead.Txt

❍ gavrasm_sources_doswin_22.zip

❍ gavrasm_sources_lin_22.zip

❍ Alle Instruktionen: instr.asm

❍ Alle Instruktionen (DOS/WIN-Format): instr_doswin.asm

❍ All Instruktionen (Linux Format): instr_linux.asm

❍ Einführung in Gerd's AVR Assembler

● Gerd's AVR Assembler Caller


❍ Software (Win): gavrasmW.zip

❍ LiesMich.txt

● Akkuload - ein Mikroprozessor-gesteuertes Ladegerät


❍ Akkulader_Beschreibung.pdf

❍ Deutsche Download-Seite

■ Quellcode gesamt: akkuload.zip

■ Quellcode Hauptprogramm: akkuload.asm

■ Quellcode akkuuart.asm

■ Quellcode akkucalc.asm

■ Quellcode akkukey.asm

■ Quellcode akkulcd.asm

❍ Schaltbild Prozessorteil, GIF-Format

❍ Schaltbild Analogteil, GIF-Format

❍ Schaltbild Prozessorteil, PDF-Format

● Links zu allen Quelldateien dieses Tutorials


❍ 8515std.asm

❍ adc8.asm

❍ avr_pwm1.pas

❍ dcf77uhr.asm

❍ div8d.asm

❍ eieruhr.asm

❍ fp_conv10_de.asm

❍ fp_conv8_de.asm

❍ konvert.asm

❍ lcd_inc.asm

❍ lcd_test.asm

❍ Lcd4Inc.asm

❍ Lcd4IncC.asm

❍ mult8.asm

❍ musik.asm

❍ pcm2pwg4.asm

❍ pwgsio2.asm

❍ r2r.pas

❍ sawtooth1.asm

❍ sawtooth2.asm

❍ sine8_25.txt

❍ sinewave.asm

❍ sinewave.pas

❍ siohex.asm

❍ test1.asm

❍ test2.asm

❍ test3.asm

❍ test4.asm

❍ testeep.asm

❍ testjmp.asm

❍ testkbd.asm

❍ testlcd.asm

❍ testlpm.asm

❍ testmac1.asm

❍ testmac2.asm

❍ testmac3.asm

❍ testram.asm

❍ testsio.asm

❍ triangle.asm

http://www.avr-asm-tutorial.net/sitemap_de.html (1 of 2)1/20/2009 7:29:18 PM


Sitemap der Webseite http://www.avr-asm-tutorial.net

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/sitemap_de.html (2 of 2)1/20/2009 7:29:18 PM


Anfänger's Einführung in AVR-Assembler

Pfad: Home => AVR-Überblick => Programmiertechniken => Menue

Programmiertechnik für Anfänger in


Hauptseite AVR Assemblersprache
Hardware
Interface Die folgenden Seiten wenden sich an Menschen, die das erste Mal in
Progr Assembler programmieren möchten und mit der Programmierung von
Exp2313 ATMEL-AVRs AT90Sxxxx beginnen wollen. Es werden ein paar
Boards grundlegende Techniken vorgestellt, die mit der Zeit und mit fortgeschrittener
Warum Asm? Programmierübung immer wieder benötigt werden und mit denen man sich
Werkzeuge daher zu Beginn vertraut machen sollte. Hier kann man auch das eine oder
Edit andere nachschlagen und in Tabellen wühlen.
Asm
ISP Themenüberblick der Programmiertechniken
Studio3
Studio4
Thema Erläuterung Befehle
Struktur
Register ISP-Interface, Parallelport-
Was? Hardware Programmierer, 2313- -
Welche? Experimentierboard, fertige Boards
Zeiger Warum Warum eigentlich Assembler lernen? -
Tabellen
Wahl Editor, Assembler, ISP, Studio3,
Werkzeuge -
Ports Studio4, Struktur
Was? Was ist ein Register? .DEF, LDI, MOV
Welche?
Status
Welche unterschiedlichen Register es CLR, ANDI, CBR, CPI,
SRAM gibt SBCI, SBR, SER, SUBI
Was? Register LD, ST, LPM, ADIW,
Register als Zeiger
Wozu? SBIW, .DB, .DW
Wie?
Was sollte man in welches Register
Stack -
packen?
Ablauf
Reset .INCLUDE, OUT, IN,
Was ist ein Port?
Verzweig CBI, SBI, SLEEP
Timing Ports
Welche Ports gibt es? -
Makros
Unterprog Statusregister als wichtigster Port CLx, SEx, BCLR, BSET
Interrupts Was ist das SRAM? -
Rechnen
Wozu braucht man SRAM? -
Zahlen
Bits
SRAM STS, LDS, LD, ST,
Wie verwendet man das SRAM?
Schieben STD, LDD
Add, Sub
PUSH, POP, RCALL,
Umwandlung Stack im SRAM
RET
Tabellen
Befehle Was passiert beim Reset? -
funktional .CSEG, .ORG, .ESEG,
alphabetisch Lineare Programmabläufe und
INC, BRNE, BREQ,
Ports Verzweigung
BRxx
funktional
alphabetisch Timing von Befehlen NOP, DEC
Vektoren
Ablauf
Makros .MACRO, .ENDMACRO
Abkürzungen
Direktiven RET, RCALL, RJMP,
Fortgeschr Unterprogramme SBRC, SBRS, SBIC,
Ausdrücke SBIS
Linksschieben Interrupts RETI
AVR-Seite Zahlen und Zeichen -
Home
ORI, OR, ANDI, AND,
CBR, SBR, EOR, COM,
Bitmanipulationen
NEG, BLD, CLT, SET,
BST
Rechnen
LSL, LSR, ASR, ROL,
Schieben und Rotieren
ROR, SWAP
ADD, ADC, SUB, SBC,
Addieren, Subtrahieren, Vergleichen
CP, CPC, CPI, TST
Zahlenumwandlung .DB, .DW
Befehle nach Funktion -
Befehle alphabetisch -
Ports -
Tabellen Vektoren -
Abkürzungen -
Direktiven alle .
Ausdrücke -

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/index.html1/20/2009 7:29:24 PM
Programmiertechniken AVR Assembler

Pfad: Home => AVR-Überblick => Programmiertechniken => Menue

Programmiertechnik für Anfänger in AVR


Assemblersprache
Die folgenden Seiten wenden sich an Menschen, die das erste Mal in Assembler programmieren
möchten und mit der Programmierung von ATMEL-AVRs AT90Sxxxx beginnen wollen. Es werden
ein paar grundlegende Techniken vorgestellt, die mit der Zeit und mit fortgeschrittener
Programmierübung immer wieder benötigt werden und mit denen man sich daher zu Beginn vertraut
machen sollte. Hier kann man auch das eine oder andere nachschlagen und in Tabellen wühlen.

Themenüberblick der Programmiertechniken

Thema Erläuterung Befehle


ISP-Interface, Parallelport-Programmierer, 2313-
Hardware -
Experimentierboard, fertige Boards
Warum Warum eigentlich Assembler lernen? -
Werkzeuge Editor, Assembler, ISP, Studio3, Studio4, Struktur -
Was ist ein Register? .DEF, LDI, MOV
CLR, ANDI, CBR, CPI, SBCI,
Welche unterschiedlichen Register es gibt
SBR, SER, SUBI
Register
LD, ST, LPM, ADIW, SBIW, .
Register als Zeiger
DB, .DW
Was sollte man in welches Register packen? -
.INCLUDE, OUT, IN, CBI, SBI,
Was ist ein Port?
SLEEP
Ports
Welche Ports gibt es? -
Statusregister als wichtigster Port CLx, SEx, BCLR, BSET
Was ist das SRAM? -
Wozu braucht man SRAM? -
SRAM
Wie verwendet man das SRAM? STS, LDS, LD, ST, STD, LDD
Stack im SRAM PUSH, POP, RCALL, RET
Was passiert beim Reset? -
.CSEG, .ORG, .ESEG, INC,
Lineare Programmabläufe und Verzweigung
BRNE, BREQ, BRxx
Timing von Befehlen NOP, DEC
Ablauf
Makros .MACRO, .ENDMACRO
RET, RCALL, RJMP, SBRC,
Unterprogramme
SBRS, SBIC, SBIS
Interrupts RETI
Zahlen und Zeichen -
ORI, OR, ANDI, AND, CBR,
Bitmanipulationen SBR, EOR, COM, NEG, BLD,
CLT, SET, BST
Rechnen LSL, LSR, ASR, ROL, ROR,
Schieben und Rotieren
SWAP
ADD, ADC, SUB, SBC, CP,
Addieren, Subtrahieren, Vergleichen
CPC, CPI, TST
Zahlenumwandlung .DB, .DW
Befehle nach Funktion -
Befehle alphabetisch -
Ports -
Tabellen Vektoren -
Abkürzungen -
Direktiven alle .
Ausdrücke -

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/rechts.html1/20/2009 7:29:29 PM
Befehle in AVR-Assemblersprache

Pfad: Home => AVR-Überblick => Programmiertechniken => Tabellen

Programmiertechniken in AVR
Assemblersprache
Tabellen
● Befehle nach Funktion geordnet
● Befehle alphabetisch
● Ports
● Abkürzungen

Befehle nach Funktion geordnet


Zur Erklärung über Abkürzungen bei Parametern siehe die Liste der Abkürzungen.
Funktion Unterfunktion Befehl Flags Clk
0 CLR r1 ZNV 1
Register
255 SER rh 1
setzen
Konstante LDI rh,k255 1
Register => Register MOV r1,r2 1
SRAM => Register, direkt LDS r1,k65535 2
SRAM => Register LD r1,rp 2
SRAM => Register mit INC LD r1,rp+ 2
DEC, SRAM => Register LD r1,-rp 2
SRAM, indiziert => Register LDD r1,ry+k63 2
Port => Register IN r1,p1 1
Stack => Register POP r1 2
Kopieren
Programmspeicher Z => R0 LPM 3
Register => SRAM, direkt STS k65535,r1 2
Register => SRAM ST rp,r1 2
Register => SRAM mit INC ST rp+,r1 2
DEC, Register => SRAM ST -rp,r1 2
Register => SRAM, indiziert STD ry+k63,r1 2
Register => Port OUT p1,r1 1
Register => Stack PUSH r1 2
8 Bit, +1 INC r1 ZNV 1
8 Bit ADD r1,r2 ZCNVH 1
Addition
8 Bit+Carry ADC r1,r2 ZCNVH 1
16 Bit, Konstante ADIW rd,k63 ZCNVS 2
8 Bit, -1 DEC r1 ZNV 1
8 Bit SUB r1,r2 ZCNVH 1
8 Bit, Konstante SUBI rh,k255 ZCNVH 1
Subtraktion
8 Bit - Carry SBC r1,r2 ZCNVH 1
8 Bit - Carry, Konstante SBCI rh,k255 ZCNVH 1
16 Bit SBIW rd,k63 ZCNVS 2
Logisch, links LSL r1 ZCNV 1
Logisch, rechts LSR r1 ZCNV 1
Rotieren, links über Carry ROL r1 ZCNV 1
Schieben
Rotieren, rechts über Carry ROR r1 ZCNV 1
Arithmetisch, rechts ASR r1 ZCNV 1
Nibbletausch SWAP r1 1
Und AND r1,r2 ZNV 1
Und, Konstante ANDI rh,k255 Z N V 1
Oder OR r1,r2 ZNV 1
Binär Oder, Konstante ORI rh,k255 ZNV 1
Exklusiv-Oder EOR r1,r2 ZNV 1
Einer-Komplement COM r1 ZCNV 1
Zweier-Komplement NEG r1 ZCNVH 1
Register, Setzen SBR rh,k255 ZNV 1
Register, Rücksetzen CBR rh,255 ZNV 1

Bits Register, Kopieren nach T-Flag BST r1,b7 T 1


ändern Register, Kopie von T-Flag BLD r1,b7 1
Port, Setzen SBI pl,b7 2
Port, Rücksetzen CBI pl,b7 2
Zero-Flag SEZ Z 1
Carry Flag SEC C 1
Negativ Flag SEN N 1

Statusbit Zweierkompliment Überlauf Flag SEV V 1


setzen Halbübertrag Flag SEH H 1
Signed Flag SES S 1
Transfer Flag SET T 1
Interrupt Enable Flag SEI I 1
Zero-Flag CLZ Z 1
Carry Flag CLC C 1
Negativ Flag CLN N 1

Statusbit Zweierkompliment Überlauf Flag CLV V 1


rücksetzen Halbübertrag Flag CLH H 1
Signed Flag CLS S 1
Transfer Flag CLT T 1
Interrupt Enable Flag CLI I 1
Register, Register CP r1,r2 ZCNVH 1
Register, Register + Carry CPC r1,r2 ZCNVH 1
Vergleiche
Register, Konstante CPI rh,k255 ZCNVH 1
Register, ≤0 TST r1 ZNV 1
Relativ RJMP k4096 2
Indirekt, Adresse in Z IJMP 2

Unbedingte Unterprogramm, relativ RCALL k4096 3


Verzweigung Unterprogramm, Adresse in Z ICALL 3
Return vom Unterprogramm RET 4
Return vom Interrupt RETI I 4
Statusbit gesetzt BRBS b7,k127 1/2
Statusbit rückgesetzt BRBC b7,k127 1/2
Springe bei gleich BREQ k127 1/2
Springe bei ungleich BRNE k127 1/2
Springe bei Überlauf BRCS k127 1/2
Springe bei Carry=0 BRCC k127 1/2
Springe bei gleich oder größer BRSH k127 1/2
Springe bei kleiner BRLO k127 1/2
Springe bei negativ BRMI k127 1/2

Bedingte Springe bei positiv BRPL k127 1/2


Verzweigung Springe bei größer oder gleich (Vorzeichen) BRGE k127 1/2
Springe bei kleiner Null (Vorzeichen) BRLT k127 1/2
Springe bei Halbübertrag BRHS k127 1/2
Springe bei HalfCarry=0 BRHC k127 1/2
Springe bei gesetztem T-Bit BRTS k127 1/2
Springe bei gelöschtem T-Bit BRTC k127 1/2
Springe bei Zweierkomplementüberlauf BRVS k127 1/2
Springe bei Zweierkomplement-Flag=0 BRVC k127 1/2
Springe bei Interrupts eingeschaltet BRIE k127 1/2
Springe bei Interrupts ausgeschaltet BRID k127 1/2
Registerbit=0 SBRC r1,b7 1/2/3
Registerbit=1 SBRS r1,b7 1/2/3
Bedingte
Portbit=0 SBIC pl,b7 1/2/3
Sprünge
Portbit=1 SBIS pl,b7 1/2/3
Vergleiche, Sprung bei gleich CPSE r1,r2 1/2/3
No Operation NOP 1
Andere Sleep SLEEP 1
Watchdog Reset WDR 1

Zum Seitenanfang

Befehlsliste alphabetisch

Assemblerdirektiven

.CSEG
.DB
.DEF
.DW
.ENDMACRO
.ESEG
.EQU
.INCLUDE
.MACRO
.ORG

Befehle

ADC r1,r2
ADD r1,r2
ADIW rd,k63
AND r1,r2
ANDI rh,k255, Register
ASR r1
BLD r1,b7
BRCC k127
BRCS k127
BREQ k127
BRGE k127
BRHC k127
BRHS k127
BRID k127
BRIE k127
BRLO k127
BRLT k127
BRMI k127
BRNE k127
BRPL k127
BRSH k127
BRTC k127
BRTS k127
BRVC k127
BRVS k127
BST r1,b7
CBI pl,b7
CBR rh,255, Register
CLC
CLH
CLI
CLN
CLR r1
CLS
CLT, Anwendung
CLV
CLZ
COM r1
CP r1,r2
CPC r1,r2
CPI rh,k255, Register
CPSE r1,r2
DEC r1
EOR r1,r2
ICALL
IJMP IN r1,p1
INC r1
LD rp,(rp,rp+,-rp) (Register), SRAM-Zugriff, Ports
LDD r1,ry+k63
LDI rh,k255 (Register), Pointer
LDS r1,k65535
LPM
LSL r1
LSR r1
MOV r1,r2
NEG r1
NOP
OR r1,r2 ORI rh,k255 OUT p1,r1
POP r1, in Int-Routine
PUSH r1, in Int-Routine
RCALL k4096
RET, in Int-Routine
RETI
RJMP k4096
ROL r1
ROR r1
SBC r1,r2
SBCI rh,k255
SBI pl,b7
SBIC pl,b7
SBIS pl,b7
SBIW rd,k63
SBR rh,255, Register
SBRC r1,b7
SBRS r1,b7
SEC
SEH
SEI, in Int-Routine
SEN
SER rh
SES
SET, Anwendung
SEV
SEZ
SLEEP
ST (rp/rp+/-rp),r1 (Register), SRAM-Zugriff, Ports
STD ry+k63,r1
STS k65535,r1
SUB r1,r2
SUBI rh,k255
SWAP r1
TST r1
WDR

Zum Seitenanfang

Ports, alphabetisch
ACSR, Analog Comparator Control and Status Register
DDRx, Port x Data Direction Register
EEAR, EEPROM Adress Register
EECR, EEPROM Control Register
EEDR, EEPROM Data Register
GIFR, General Interrupt Flag Register
GIMSK, General Interrupt Mask Register
ICR1L/H, Input Capture Register 1
MCUCR, MCU General Control Register
OCR1A, Output Compare Register 1 A
OCR1B, Output Compare Register 1 B
PINx, Port Input Access
PORTx, Port x Output Register
SPL/SPH, Stackpointer
SPCR, Sreial Peripheral Control Register
SPDR, Serial Peripheral Data Register
SPSR, Serial Peripheral Status Register
SREG, Status Register
TCCR0, Timer/Counter Control Register, Timer 0
TCCR1A, Timer/Counter Control Register 1 A
TCCR1B, Timer/Counter Control Register 1 B
TCNT0, Timer/Counter Register, Counter 0
TCNT1, Timer/Counter Register, Counter 1
TIFR, Timer Interrupt Flag Register
TIMSK, Timer Interrupt Mask Register
UBRR, UART Baud Rate Register
UCR, UART Control Register
UDR, UART Data Register
WDTCR, Watchdog Timer Control Register

Zum Seitenanfang

Verwendete Abkürzungen
Die in diesen Listen verwendeten Abkürzungen geben den zulässigen Wertebereich mit an. Bei
Doppelregistern ist das niederwertige Byte-Register angegeben. Konstanten bei der Angabe von
Sprungzielen werden dabei automatisch vom Assembler aus den Labels errechnet.
Kategorie Abk. Bedeutung Wertebereich
r1 Allgemeines Quell- und Zielregister
R0..R31
r2 Allgemeines Quellregister
rh Oberes Register R16..R31
Register R24(R25), R26(R27), R28(R29), R30
rd Doppelregister
(R31)
rp Pointerregister X=R26(R27), Y=R28(R29), Z=R30(R31)
ry Pointerregister mit Ablage Y=R28(R29), Z=R30(R31)
k63 Pointer-Konstante 0..63
k127 Bedingte Sprungdistanz -64..+63
Konstante k255 8-Bit-Konstante 0..255
k4096 Relative Sprungdistanz -2048..+2047
k65535 16-Bit-Adresse 0..65535
Bit b7 Bitposition 0..7
p1 Beliebiger Port 0..63
Port
pl Unterer Port 0..31

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/commands.html1/20/2009 7:29:34 PM
Register im AVR

Pfad: Home => AVR-Überblick => Programmiertechniken => Register

Programmiertechnik für Anfänger in AVR


Assemblersprache
Was ist ein Register?
Register sind besondere Speicher mit je 8 Bit Kapazität. Sie sehen bitmäßig daher etwa so aus:
7 6 5 4 3 2 1 0

Man merke sich die Nummerierung der Bits: sie beginnt immer bei Null.
In einen solchen Speicher passen Zahlen von 0 bis 255 (Ganzzahl ohne Vorzeichen), von -128 bis
+127 (Ganzzahl mit Vorzeichen in Bit 7), ein Acht-Bit- ASCII-Zeichen wie z.B. 'A' oder auch acht
einzelne Bits, die sonst nix miteinander zu tun haben (z.B. einzelne Flaggen oder Flags).
Das Besondere an diesen Registern (im Gegensatz zu anderen Speichern) ist, dass sie

● direkt in Befehlen verwendet werden können, da sie direkt an das Rechenwerk, den
Akkumulator, angeschlossen sind,
● Operationen mit ihrem Inhalt mit nur einem Befehlswort ausgeführt werden können,
● sowohl Quelle von Daten als auch Ziel des Ergebnisses der Operation sein können.

Es gibt 32 davon in jedem AVR. Auch der kleinste Typ hat schon so viele davon. Das macht die
AVR ziemlich einzigartig, da dadurch viele Kopieraktionen und der langsamere Zugriff auf andere
Speicherarten oft nicht nötig ist. Die Register werden mit R0 bis R31 bezeichnet, man kann ihnen mit
einer Assemblerdirektive aber auch einen etwas wohlklingenderen Namen verpassen, wie z.B.

.DEF MeinLieblingsregister = R16

Assemblerdirektiven gibt es einige (mehr Assemblerdirektiven gibt es hier), sie stellen Regie-
Anweisungen an den Assembler dar und erzeugen selbst keinen ausführbaren Code. Sie beginnen
immer mit einem Punkt.

Statt des Registernamens R16 wird dann fürderhin immer der neue Name verwendet. Das könnte also
ein schreibintensives Programm werden.

Mit dem Befehl

LDI MeinLieblingsRegister, 150

was in etwa bedeutet: Lade die Zahl 150 in das Register R16, aber hurtig, (in englisch: LoaD
Immediate) wird ein fester Wert oder eine Konstante in mein Lieblingsregister geladen. Nach dem
Übersetzen (Assemblieren) ergibt das im Programmspeicher etwa folgendes Bild:

000000 E906

In E906 steckt sowohl der Load-Befehl als auch das Zielregister (R16) als auch die Konstante 150,
auch wenn man das auf den ersten Blick nicht sieht. Auch dies macht Assembler bei den AVR zu
einer höchst effektiven Angelegenheit: Instruktion und Konstante in einem einzigen Befehlswort und
schnell und effektiv ausgeführt. Zum Glück müssen wir uns um diese Übersetzung des Befehlsworts
nicht kümmern, das macht der Assembler für uns.

In einem Befehl können auch zwei Register vorkommen. Der einfachste Befehl dieser Art ist der
Kopierbefehl MOV. Er kopiert den Inhalt des einen Registers in ein anderes Register. Also etwa so:

.DEF MeinLieblingsregister = R16


.DEF NochEinRegister = R15
LDI MeinLieblingsregister, 150
MOV NochEinRegister, MeinLieblingsregister

Die ersten beiden Zeilen dieses großartigen Programmes sind Direktiven, die ausschließlich dem
Assembler mitteilen, dass wir anstelle der beiden Registernamen R16 und R15 andere Benennungen
zu verwenden wünschen. Sie erzeugen keinen Code! Die beiden Programmzeilen mit LDI und MOV
erzeugen Code, nämlich:

000000 E906
000001 2F01

Der zweite Befehl schiebt die 150 im Register R16 in das Rechenwerk und kopiert dessen Inhalt in
das Zielregister R15. MERKE:

Das erstgenannte Register im Assemblerbefehl ist immer das Zielregister, das das Ergebnis aufnimmt!

(Also so ziemlich umgekehrt wie man erwarten würde und wie man es ausspricht. Deshalb sagen
viele, Assembler sei schwer zu lernen!)

Zum Seitenanfang

Unterschiede der Register


Schlaumeier würden das obige Programm vielleicht eher so schreiben:

.DEF NochEinRegister = R15


LDI NochEinRegister, 150

Und sind reingefallen: Nur die Register R16 bis R31 lassen sich hurtig mit einer Konstante laden, die
Register R0 bis R15 nicht! Diese Einschränkung ist ärgerlich, ließ sich aber bei der Konstruktion der
Assemblersprache für die AVRs wohl kaum vermeiden.

Es gibt eine Ausnahme, das ist das Nullsetzen eines Registers. Dieser Befehl

CLR MeinLieblingsRegister

ist für alle Register zulässig.

Diese zwei Klassen von Registern gibt es ausser bei LDI noch bei folgenden Befehlen:

● ANDI Rx,K ; Bit-Und eines Registers Rx mit einer Konstante K,


● CBR Rx,M ; Lösche alle Bits im Register Rx, die in der Maske M (eine Konstante) gesetzt
sind,
● CPI Rx,K ; Vergleiche das Register Rx mit der Konstante K,
● SBCI Rx,K ; Subtrahiere die Konstante K und das Carry-Flag vom Wert des Registers Rx und
speichere das Ergebnis im Register Rx,
● SBR Rx,M ; Setze alle Bits im Register Rx, die auch in der Maske M (eine Konstante) gesetzt
sind,
● SER Rx ; Setze alle Bits im Register Rx (entspricht LDI Rx,255),
● SUBI Rx,K ; Subtrahiere die Konstante K vom Inhalt des Registers Rx und speichere das
Ergebnis in Register Rx.

Rx muss bei diesen Befehlen ein Register zwischen R16 und R31 sein! Wer also vorhat, solche
Befehle zu verwenden, sollte ein Register oberhalb von R15 dafür auswählen. Das programmiert sich
dann leichter. Noch ein Grund, die Register mittels .DEF umzubenennen: in größeren Programmen
wechselt sich leichter ein Register, wenn man ihm einen besonderen Namen gegeben hat.

Zum Seitenanfang

Pointer-Register
Noch wichtigere Sonderrollen spielen die Registerpaare R26/R27, R28/R29 und R30/R31. Diese
Pärchen sind so wichtig, dass man ihnen in der AVR-Assemblersprache extra Namen gegeben hat: X,
Y und Z. Diese Doppelregister sind als 16-Bit-Pointerregister definiert. Sie werden gerne bei
Adressierungen für internes oder externes RAM verwendet (X, Y und Z) oder als Zeiger in den
Programmspeicher (Z).

Bei den 16-Bit-Pointern befindet sich das niedrigere Byte der Adresse im niedrigeren Register, das
höherwertige Byte im höheren Register. Die beiden Teile haben wieder eigene Namen, nämlich ZH
(höherwertig, R31) und ZL (niederwertig, R30). Die Aufteilung in High und Low geht dann etwa
folgendermaßen:

.EQU Adresse = RAMEND ; In RAMEND steht die höchste SRAM-Adresse des Chips
LDI YH,HIGH(Adresse)
LDI YL,LOW(Adresse)

Für die Pointerzugriffe selbst gibt es eine Reihe von Spezial-Zugriffs-Kommandos zum Lesen
(LD=Load) und Schreiben (ST=Store), hier am Beispiel des X-Zeigers:
Zeiger Vorgang Beispiele
LD R1,X
X Lese/Schreibe von der Adresse X und lasse den Zeiger unverändert
ST X,R1
LD R1,X+
X+ Lese/Schreibe von der Adresse X und erhöhe den Zeiger anschließend um Eins
ST X+,R1
Vermindere den Zeiger um Eins und lese/schreibe dann erst von der neuen LD R1,-X
-X
Adresse ST -X,R1
Analog geht das mit Y und Z ebenso.

Für das Lesen aus dem Programmspeicher gibt es nur den Zeiger Z und den Befehl LPM. Er lädt das
Byte an der Adresse Z in das Register R0. Da im Programmspeicher jeweils Worte, also zwei Bytes
stehen, wird die Adresse mit zwei multipliziert und das unterste Bit gibt jeweils an, ob das untere
oder obere Byte des Wortes im Programmspeicher geladen werden soll. Also etwa so:

LDI ZH,HIGH(2*Adresse)
LDI ZL,LOW(2*Adresse)
LPM

Nach Erhöhen des Zeigers um Eins wird das zweite Byte des Wortes im Programmspeicher gelesen.
Da die Erhöhung des 16-Bit-Speichers um Eins auch oft vorkommt, gibt es auch hierfür einen
Spezialbefehl für Zeiger:

ADIW ZL,1
LPM

ADIW heisst soviel wie ADdiere Immediate Word und kann bis maximal 63 zu dem Wort addieren.
Als Register wird dabei immer das untere Zeigerregister angegeben (hier: ZL). Der analoge Befehl
zum Zeiger vermindern heißt SBIW (SuBtract Immediate Word). Anwendbar sind die beiden Befehle
auf die Registerpaare X, Y und Z sowie auf das Doppelregister R24/R25, das keinen eigenen Namen
hat und auch keinen Zugriff auf RAM- oder sonstige Speicher erm•glicht. Es kann als 16-Bit-Wert
optimal verwendet werden.

Wie bekommt man aber nun die Werte, die ausgelesen werden sollen, in den Programmspeicher?
Dazu gibt es die DB- und DW-Anweisungen für den Assembler. Byteweise Listen werden so erzeugt:

.DB 123,45,67,78 ; eine Liste mit vier Bytes


.DB "Das ist ein Text. " ; eine Liste mit einem Text

Auf jeden Fall ist darauf achten, dass die Anzahl der einzufügenden Bytes pro Zeile geradzahlig sein
muss. Sonst fügt der Assembler ein Nullbyte am Ende hinzu, das vielleicht gar nicht erwünscht ist.
Das Problem gibt es bei wortweise organisierten Tabellen nicht. Die sehen so aus:

.DW 12345,6789 ; zwei Worte

Statt der Konstanten können selbstverständlich auch Labels (Sprungadressen) eingefügt werden, also
z.B. so:

Label1:
[... hier kommen irgendwelche Befehle...]
Label2:
[... hier kommen noch irgendwelche Befehle...]
Sprungtabelle:
.DW Label1,Label2

Beim Lesen per LPM erscheint übrigens das niedrigere Byte der 16-Bit-Zahl zuerst!

Und noch was für Exoten, die gerne von hinten durch die Brust ins Auge programmieren: Die
Register sind auch mit Zeigern lesbar und beschreibbar. Sie liegen an der Adresse 0000 bis 001F. Das
kann man nur gebrauchen, wenn man auf einen Rutsch eine Reihe von Registern in das RAM
kopieren will oder aus dem RAM laden will. Lohnt sich aber erst ab 5 Registern.

Zum Seitenanfang

Empfehlungen zur Registerwahl


1. Register immer mit der .DEF-Anweisung festlegen, nie direkt verwenden.
2. Werden Pointer-Register für RAM u.a. benötigt, R26 bis R31 dafür reservieren.
3. 16-Bit-Zähler oder ähnliches realisiert man am besten in R24/R25.
4. Soll aus dem Programmspeicher gelesen werden, Z (R30/31) und R0 dafür reservieren.
5. Werden oft konstante Werte oder Zugriffe auf einzelne Bits in einem Register verwendet,
dann die Register R16 bis R23 dafür vorzugsweise reservieren.
6. Für alle anderen Anwendungsfälle vorzugsweise R1 bis R15 verwenden.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/register.html1/20/2009 7:29:38 PM
Direktiven und Ausdrücke in AVR-Assemblersprache

Pfad: Home => AVR-Überblick => Programmiertechniken => Direktiven/Ausdrücke

Programmiertechniken in AVR
Assemblersprache
Assembler-Direktiven
Assembler-Direktiven steuern den Assembler, sie erzeugen für sich betrachtet keinen eigenen Code.
Der einleitende Punkt muss in Spalte 1 beginnen.
Segment Direktive Beschreibung
Definiert den Typ des Zielprozessors und legt verfügbaren Satz an
.DEVICE Instruktionen fest (ungültige Instruktionen für den Typ werden mit
Fehlermeldung quittiert, Syntax .DEVICE AT90S8515)
.DEF Legt ein Synonym für ein Register fest (z.B. .DEF MeinReg = R16)
Definiert ein Symbol und legt seinen Wert fest (kann später umdefiniert
Kopf .EQU werden, Syntax .EQU test = 1234567, interne Speicherung des Wertes
erfolgt als 4-Byte-Integer-Zahl)
.SET Fixiert den Wert eines Symboles (keine spätere Neudefinition möglich)
Fügt eine externe Datei ein, als ob deren Inhalt an dieser Stelle stünde
.INCLUDE (Typisch z.B. Einbinden der Headerdatei: .INCLUDE "C:\avrtools
\appnotes\8515def.inc")
Beginn des Codesegmentes (alles was danach folgt, wird als Code
.CSEG
übersetzt und in den Programmraum gespeichert)
Fügt ein oder mehrere konstante Bytes in das Programm (kann eine Zahl
von 0..255 sein, ein ASCII-Zeichen 'c', eine Zeichenkette "abcde" oder
ein Gemisch wie z.B. 1,2,3,'a',"abc". Im Programmraum muss die
.DB
Anzahl der eingefügten Bytes geradzahlig sein, weil der
Programmspeicher immer nur ganze 16-Bit-Worte enthalten kann,
andernfalls wird vom Assembler ein Nullbyte angefügt.)
Code Fügt ein binäres Wort in den Programmraum ein (produziert z.B. eine
.DW
Tabelle im Code!)
Makros werden in die Listdatei aufgenommen (ohne diese Angabe wird
.LISTMAC
Code aus Makros nicht im .LST-file ausgegeben)
Beginn eines Makros (Code wird nicht erzeugt, erst bei Aufruf des
.MACRO Makros mit seinem Name (Syntax: .MACRO makroname parameter,
Aufruf mit: makroname parameter)
.ENDMACRO Ende des Makros
Beginn des EEPROM-Speichers (die erzeugten Inhalte landen beim
.ESEG
Programmieren im EEPROM-Segment)
Fügt ein oder mehrere konstante Bytes in das EEPROM ein (kann eine
EEPROM .DB Zahl von 0..255 sein, ein ASCII-Zeichen 'c', eine Zeichenkette "abcde"
oder ein Gemisch wie z.B. 1,2,3,'a',"abc".)
Fügt ein binäres Wort in den EEPROM-Raum ein (Im EEPROM-
.DW
Segment wird erst das niedrigere, dann das höhere Byte eingefügt)
Beginn des Datensegments (hier dürfen dann nur BYTE-Direktiven und
.DSEG Labels stehen, bei der Übersetzung werden nur die Labels entsprechend
SRAM ausgewertet)
Reserviert ein oder mehrere Bytes im Datensegment (fügt den Bytewert
.BYTE
im Unterschied zu .DB nicht wirklich ein!)
Legt die Anfangsadresse im jeweiligen Segment fest (z.B. .ORG
.ORG
0x0000)
Schaltet die Listing-Ausgabe ein (der produzierte Code wird
.LIST
menschenlesbar in einer .LST-Datei ausgegeben)
Überall .NOLIST Schaltet die Ausgabe in die .LST-Datei aus
Fügt eine externe Datei ein, als ob deren Inhalt an dieser Stelle stünde
.INCLUDE (Typisch z.B. Einbinden der Headerdatei: .INCLUDE "C:\avrtools
\appnotes\8515def.inc")
.EXIT Ende des Assembler-Codes (stellt weitere Übersetzung ein)

Fortgeschrittene Assemblerdirektiven
Fortgeschrittene Assemblerdirektiven erlauben

● bedingtes Assemblieren: ein Code wird nur dann übersetzt, wenn eine Bedingung gegeben
oder nicht gegeben ist, andernfalls wird ein anderer Code übersetzt,
● Ausgaben von Nachrichten oder erzwungenen Fehlern: dient zur Benachrichtigung während
der Übersetzung bzw. erzwingt einen Abbruch der Übersetzung.

Es ist wichtig zu beachten, dass sich die Direktiven nur an den Assembler richten und sein Verhalten
steuern, im erzeugten Programm selbst finden keine Verzweigungen statt!

Nicht alle Assembler kennen diese Direktiven. Neuere Assembler von ATMEL, die neueren
Studioversionen sowie gavrasm kennen diese Direktiven.

Die Syntax dieser Direktiven sieht so aus:

● .IF <Bedingung>, dann Codezeilen, dann .ENDIF. Bedingung ist ein Ausdruck, der entweder
wahr oder falsch sein kann, also z.B. ein Vergleich wie a<b, a>b oder a==b.
● .IF <Bedingung>, dann Codezeilen, dann .ELSE, dann Codezeilen, dann .ENDIF. Wenn die
Bedingung erfüllt ist, werden die ersten Codezeilen übersetzt, wenn nicht die zweiten hinter
ELSE.
● .IF <Bedingung 1>, dann Codezeilen, dann .ELIF <Bedingung 2>, dann Codezeilen, dann .
ENDIF. Wenn Bedingung 1 wahr ist, wird der erste Code erzeugt, wenn nicht wird die
Bedingung 2 geprüft. Ist diese erfüllt, wird der zweite Code erzeugt. Wenn weder Bedingung
1 noch 2 erfüllt sind, wird gar kein Code erzeugt.
● .IFDEF <Symbol>. Prüft, ob ein Symbol definiert ist. Wenn ja, dann wird der Code übersetzt,
wenn nein, dann nicht. Kann mit den ELSE- und ELIF- Direktiven kombiniert werden und ist
mit der ENDIF-Direktive abzuschließen.
● .IFNDEF <Symbol>. Bewirkt das Umgekehrte: wenn das Symbol nicht definiert ist, wird
übersetzt.
● .MESSAGE "<text>". Gibt den Nachrichtentext beim Übersetzen aus. Kann in Kombination
mit der bedingten Assemblierung dazu benutzt werden, um einen Hinweis auf das Ergebnis
der Verzweigung zu geben.
● .ERROR "<text>". Gibt den Nachrichtentext aus und erzeugt eine Fehlermeldung. Kann
benutzt werden, um unter bestimmten Bedingungen die Assemblierung zu beenden, z.B. wenn
ein Wert zu groß oder zu klein ist.

Assembler-Ausdrücke
Ausdrücke werden für Berechnungen im Assembler-Quelltext verwendet und werden bei der
Übersetzung des Codes ausgewertet. Sie erzeugen keinen ausführbaren Code.
Typ Zeichen Beschreibung
+ Addition
- Subtraktion oder negative Zahl
Rechnen
* Multiplikation
/ Ganzzahlen-Division
& Bitweise UND-Verknüpfung
| Bitweise ODER-Verknüpfung
^ Bitweise Exklusive-ODER-Verknüpfung
Binär
~ Bitweise NICHT-Verknüpfung
<< Linksschieben
>> Rechtsschieben
< Kleiner als
> Größer als
== Gleich
<= Kleiner gleich
Logisch >= Größer gleich
!= Ungleich
&& UND-Verknüpfung
|| ODER-Verknüpfung
! NICHT

Links schieben
Anmerkung zum Linksschieben (<<): sehr häufig sind z.B. folgende Zeilen zu sehen:

ldi r16,1<<ADSC
out ADCSRA,r16

Dabei ist ADSC ein in der Headerdatei definiertes einzelnes Bit in einem Port (hier: das Bit, das eine
AD-Umwandlung startet, bei den meisten Mega-Typen eine 6), ADCSRA ist ein ebenfalls im Header
definierter Port. Der Ausdruck << bewirkt dabei, dass eine Eins (binär 0000.0001) genau sechs Mal
links geschoben wird und zu 0100.0000 wird. Diese Zahl wird an den Port ADCSRA ausgegeben.

Die Verwendung dieser Konstruktion hat den Vorteil, dass die genaue Lage des ADSC-Bits im Port
ADCSRA gar nicht bekannt sein muss und sich von Headerdatei zu Headerdatei ändern kann, ohne
dass der Quellcode geändert werden müsste. Gegenüber der Konstruktion

ldi r16,0b01000000
out 0x06,r16

erhöht sich auch noch immens die Transparenz, weil doch ziemlich kryptisch bleibt, was denn nun
hier genau gemacht werden soll. Außerdem erspart man sich die Mühe, die Nullen exakt abzuzählen.

Was nun, wenn man gleichzeitig auch noch andere Bits in diesem Port setzen möchte, wie z.B. das
Interrupt-Enable-Bit ADIE (Bit 3)? Dann muss bitweise ODER-verknüpft werden:

ldi r16,(1<<ADSC) | (1<<ADIE)


out ADCSRA,r16

Die Klammern setzen die richtigen Rechenprioritäten.

Zum Seitenanfang

©2002-2005 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/diraus.html1/20/2009 7:29:41 PM
Gerd's AVR Assembler

Pfad: Home => AVR-Assembler

Gerd's AVR Assembler


Ein Kommandozeilen-Assembler für alle AT90S-, AT90CAN-, AT90USB-, ATtiny-, ATmega- und ATxmega-
Typen der Mikroprozessoren von ATMEL mit vielen erweiterten und neuen Eigenschaften. Arbeitet auf der
DOS-, Win32- und Linux(i386)-Kommandozeile.
Durch erweiterte Fehlerprüfung und -kommentierung besonders auch für Anfänger geeignet!

Sprachen
Erster AVR-Assembler vollständig in deutscher Sprache. Leicht in andere Sprachen übersetzbar (sende mir die
übersetzte Dateien gavrlang_xx.pas und LiesMich.Txt, dann gibt es auch andere Sprachversionen). Auch in
englischer Sprache erhältlich, siehe die englische Version dieser Seite.

Eigenschaften
Siehe die LiesMich.Txt für mehr Informationen über die Eigenschaften. Eine kurze Einführung in die Nutzung
der speziellen Features von gavrasm bietet die Einführung.

Benachrichtigungsdienst bei neuen Versionen


Bitte das Mail-Formular ausfüllen und abschicken, dann gibt es Benachrichtigungen per Mail.

Neu in Version 2.2


● Auf 115 Typen erweitert, alle Eigenschaften intern gespeichert.
● Französische Sprachversion (danke Hervé)
● Verwendung interner Symbole abschaltbar mit Schalter x

Download
Version 2.2 ist verfügbar zum Download als fertig compilierte Version

● Deutsch:
❍ Linux (i386)

❍ Dos

❍ Win

● Englisch:
❍ Linux (i386)

❍ Dos

❍ Win

● Französisch:
❍ Linux (i386)

❍ Dos

❍ Win

Packe die gezippte ausführbare Datei und die LiesMich-Datei aus.

Quellcode
Quellcode zum Download, geschrieben für und getestet mit FreePascal, ist verfügbar für

● Linux und für


● DOS und Win.

Packe die gezippten Dateien aus, kopiere die sprachspezifische Version der Datei gavrlang_xx.pas und füge sie
als gavrlang.pas ein. Compiliere mit einem Pascal-Compiler (fpc, http://www.freepascal.org).

Status
Diese Software wurde ausgiebig getestet, kann aber noch Fehler enthalten. Daher Vorsicht bei der Benutzung.
Berichte über Bugs und vermisste Features bitte an gavrasm (at) avr-asm-tutorial.net, Subject=gavrasm-bug 2.2.

Frühere Versionen
Links zu älteren Versionen:

● Version 2.1 (Dezember 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 2.0 (September 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 1.9 (August 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 1.8 (Juli 2006)


● Version 1.7 (Mai 2006)
● Version 1.6 (Dezember 2005)
● Version 1.5 (September 2005)
● Version 1.4 (Juli 2005)
● Version 1.3 (Mai 2005)
● Version 1.2 (März 2005)
● Version 1.1 (Januar 2005)
● Version 1.0 (Oktober 2004)
● Version 0.9 (März 2004)
● Version 0.8 (Februar 2004)
● Version 0.7 (November 2003)
● Version 0.6 (September 2003)
● Version 0.5 (August 2003)
● Version 0.4 (Juli 2003)
● Version 0.3 (Juni 2003)
● Version 0.2 (Mai 2003)
● Version 0.1 (Dezember 2002)

©2003-2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gavrasm/index_de.html1/20/2009 7:29:44 PM
Gerd's AVR Assembler

Pfad: Home => AVR-Assembler

Gerd's AVR assembler


A command line assembler for all AT90S-, AT90CAN-, AT90USB-, ATtiny-, ATmega and ATxmega-Types of
microcontrollers of ATMEL, with many extended and new features. Works on DOS, Win32 and Linux(i386)
command lines.
Extended error checking and commenting, especially suited for the beginner in assembler programming!

Languages
AVR-Assembler in an english, french and a german version, can easily be translated to other languages (send me
your edited gavrlang_xx.pas and the ReadMe.Txt file for further translation to other languages). See the german
page for all versions.

Features
View the ReadMe.Txt for more informations on features. See also the introduction to the use and some notes on
special features of gavrasm.

Mail on new version releases


Please fill in the form and mail it to me. You'll get a mail whenever a new version of gavrasm is released.

Download
Version 2.2 is available for download as already-compiled-version for

● Linux (i386)
● Dos
● Win

Unpack the executable and a readme file. See the readme for command line options and use.

Source-Code
Source code, written for FreePascal, is available for

● Linux and for


● DOS and Win.

Unpack the zipped files, copy your desired language file gavrlang_xx.pas, rename it to gavrlang.pas and compile
with the Pascal compiler (fpc, see http://www.freepascal.org).

Status
This software was tested intensively, but may still have some bugs, so be careful with its use. Reports on bugs
and missed features to gavrasm (at) avr-asm-tutorial.net, subject=gavrasm-bug 2.2.

Earlier versions
Links to older versions:

● Version 2.1 (December 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 2.0 (September 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 1.9 (August 2006)


❍ Linux (i386)

❍ Dos

❍ Win

● Version 1.8 (July 2006)


● Version 1.7 (May 2006)
● Version 1.6 (December 2005)
● Version 1.5 (September 2005)
● Version 1.4 (July 2005)
● Version 1.3 (May 2005)
● Version 1.2 (March 2005)
● Version 1.1 (January 2005)
● Version 1.0 (October 2004)
● Version 0.9 (March 2004)
● Version 0.8 (February 2004)
● Version 0.7 (September 2003)
● Version 0.6 (September 2003)
● Version 0.5 (August 2003)
● Version 0.4 (June 2003)
● Version 0.3 (June 2003)
● Version 0.2 (May 2003)
● Version 0.1 (December 2002)

©2003-2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gavrasm/index_en.html1/20/2009 7:29:45 PM
http://www.avr-asm-tutorial.net/gavrasm/v22/ReadMe.Txt

Program gavrasm

AVR Assembler for ATMEL AVR-Processors


======================================

Command line Assembler for ATMEL AVR-Processors of the types


- AT90S
- AT90CAN
- ATtiny
- ATmega and
- ATXmega.

For Linux i386 pre-compiled executable : gavrasm


For DOS resp. Win32 compiled executable: gavrasm.exe
Sourcecode for fpc-Pascal

Calls and options


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

Call: gavrasm [-abelmqsw] SourceFile[.asm]


Parameters:
a: Switch output of ANSI-chars on/off
default is on (Linux) resp. off (Dos, Win)
b: Extended error comments for beginners
default is off
e: Longer error messages
default is off (short error messages)
l: Suppress output of the LIST-file
default is LIST-file output on
m: Suppress listing of expanded macros
default is listing on
q: No output of messages on the command line (quiet)
(except: headers and forced messages!)
default is output on
s: Output a list of symbols in the LIST-file
default is no symbol list
w: Enable wrap-around
default is wrap-around off
x: Disable using internal def.inc information
default is internal information
Output files:
SourceFile.lst ... Assembler-Listing, Textfile
SourceFile.hex ... Code in Intel-Hex-format, Textfile
SourceFile.eep ... EEPROM-content in Intel-Hex-format, Textfile,
(deleted if no .ESEG content was generated)
SourceFile.err ... Error messages (if any), Textfile

Call: gavrasm [-?hdt]


Parameters:
?: List of options
h: List of options
d: List of supported directives
t: List of supported AVR types

Remark for the option a:


The Linux version outputs ANSI code sequences by default,
with other OS's this option is disabled by default. The
option a inverts this switch under all operating systems.

Specialties of this Assembler


-----------------------------
Following only the special properties of this assembler are
discussed. All properties not mentioned explicitly, work like
in other assemblers, so these are compatible with others
(e.g. with the ATMEL(R)-assembler).

a) Main differences resulting in error and warning messages


for code that assembles correct (without any errors and
warnings) with other assemblers:
* Header files for the AVR type (*def.inc) are not necessary,
gavrasm knows them all by itself. Header files for known
AVR types, included using the INCLUDE directive, are ignored,
the file is not read. A warning is given. Instead of reading
the header file, gavrasm identifies the AVR type from that
line and, if recognized, defines its own AVR type-specific
symbol set. Be aware of that in the default mode if you
change the header file for an AVR, because these changes
don't come into effect under gavrasm. In contrast to other
assemblers, the symbols of the AVR type are already defined
with the DEVICE directive, including header files is no
longer necessary.
If you want to use self-written def.inc, then avoid using
the term "def.inc" in the filename. That prevents gavrasm
from recognizing the header file and includes it normally.
From version 2.2 on this property can be forced by using
the parameter x on the command line.
* Filenames (e.g. in the INCLUDE directive, usually do not
need to be in quotes. Under Linux always use quotes
("...") for the filename!
* Constant displacements in relative jump- or branch-
instructions, usually written like " brcc PC+10" (where
PC stands for PROGRAM COUNTER), are already recognized
if the displacement is preceeded by a '+' or '-'
character, like " brcc +10". The use of the notation PC+10
is optional.
* The extra features in interpreting text and character con-
stants, implemented in gavrasm, may cause error messages
and incompatibilites with other assemblers. The differences
in detail:
- Introducing a " within a text constant by using a double
"" is misinterpreted by other assemblers. This causes an
error message saying "garbage at end of line", the text
behind the double "" is not interpreted.
- A ; within a text string ("...;...") or as an ASCII
character constant (';') is misinterpreted by other
assemblers as beginning of a comment, they ignore all
behind the ; and produce an error message.
- If non-printable ASCII code characters are part of a
text constant, these are in gavrasm written like
"...\m\j\@". Other assemblers that do not have this
feature misinterpret the \ as a normal ASCII character.
No error message results. If the number of control
characters is odd, a warning results saying that the
number of characters is odd and a Null-char is added.
* The .ERROR directive in gavrasm expects that a text is
given as parameter, to be displayed as error message. Other
assembler don't know that. The text makes sense because one
needs to know what exactly caused the error. To get the same
effect, code for other assemblers require the use of an
additional .MESSAGE directive.

b) Source code is available and documented:


* FPK-Pascal, written and tested for Linux-(i386), DOS-(go32v2)
and Win32-FPK (use latest version, older versions have problems
with some of the Pascal instructions)
(FPK-Compiler available at http://www.freepascal.org).
Several warnings during compilation can be ignored.
* Source code files provided:
gavrasm.pas: Main program file
gavrdev.pas: Unit that provides all hardware characteristics
and symbols of all supported AVR types, *def.inc
Include files are not needed
gavrif.pas: Unit providing nested if/else/endif support
gavrlang.pas: Unit for language support (currently available
in an english (gavrlang_en.pas) and german
gavrlang_de.pas) version
gavrline.pas: Unit to split the asm lines into pieces
gavrmacr.pas: Unit for Macro-processing
gavrout.pas: Unit for Hex output
gavrsymb.pas: Unit for symbol-processing
* Prior to compilation: copy the language file gavrlang_en.pas
and rename it to gavrlang.pas! For the french version use
gavrlang_fr.pas!
* Test file for checking of the assembler:
instr.asm: Test file with all AVR instructions

c) Extra directives (Pseudo opcodes):


* DEVICE now automatically provides all symbols of the respective
AVR type, forget the *def.inc-files, you'll never need them any
more.
* The EXIT-directive without conditions works normal (interrupts
further assembling process of the currently processed file)
and is compatible with other assemblers. If an additional
parameter is given, usually a comparison, this is interpreted
as a boolean value. If this is 1 (TRUE) the EXIT directive is
executed, providing a conditional stop of the assembling
process (stops the assembling process completely). This
conditional EXIT directive also works within INCLUDE files.
This feature can be used to check for error conditions during
the assembly process (e.g. stop if limits for certain symbol
values are exceeded, as an overflow detection).
This directive can, in part, be exchanged with the directive
.ERROR, that produces an error message.
* Additional .IF, .ELSE, .ELIF and .ENDIF directive: .IF (condition)
assembles the following code only if the condition is true (1),
otherwise branches either to the code after .ELSE, .ELIF or .ENDIF.
Please use the ELIF directive as an alternative to ELSE, and do
not mix these, the result is not defined.
Allows nested .IF, .ELSE, .ELIF and .ENDIF directives of any depth.
* The .IFDEVICE parameter directive compiles the following code,
if the type specified by the parameter is equal to the one
specified in the .DEVICE statement.
* .IFDEF and .IFNDEF tests for defined and unsdefined symbols
and works like the .IF directive.
* .MESSAGE displays a message (in "..." as parameter) on the list
output, which is not suppressed in the quiet-mode.
* .ERROR forces an error with a message (in "..." as parameter) on
the list output and in the error textfile.
* Additional .SETGLOBAL p1,p2,[...] directive to export local
macro symbols. Otherwise symbols defined within a macro are
completely local and cannot be used outside of the macro. Be
careful with that feature, it might be source for errors.
* Recursive .INCLUDE-directive with unlimited depth. Under Linux,
always use quotes for the filename ("...").
* List of supported directives available by gavrasm -d

d) Makros:
* Extended macro capabilities:
- recursive macro calls without limitations
- extended parameter checking within the macro definition, not
only at the macro call itself
- all labels and symbols in macros are defined locally, they
are not accessible from outside the macro, improves error
recognition
- export of local symbols by use of the SETGLOBAL directive
- labels in macros are correct even during forward use and if
used in recursive calls
- optional use of .ENDM or .ENDMACRO to close the macro definition
- List of all defined and used macros in the listfile, if the symbol
list is switched on with -s (and by not suppressing list output
on the command line by not using the -l option or by .LIST in the
source code)

e) Improved error detection, commenting and syntax checking:


* Extended symbol checking:
- exact symbol type checking (cases R for registers, C for
constants, V for variables, T for AVR type definitions,
M for local macro labels, L for global macro labels)
- the use of mnemonics as symbol names is prohibited,
excludes those used by ATMEL within some older header
files (accepts OR and BRTS as a symbol name)
- extended recognition of undefined symbols
* Extended error commenting and warnings (more than 100
error types, 8 warning types)
* Enhanced syntax commenting for beginners (option b) for
instructions and directives in the list file
* Extended calculation check (Over- and Underrun of internal
32-bit-Integer values)
* Extended characters in literal constants and strings: ';',
'''', '\n', '\\', "abc\n\j", "abc;def"
* Separator character (dots, '.') in binary- and hex-numbers
for improved readability of the source code (e.g. 0b0001.0010,
$124A.035F, 0x82.FABC)
* BYTE1-function implemented (similiar to BYTE2 etc.)
* Allows constant displacement in relative jumps, e.g. rjmp +10 or
brcc -3 (displacement must start with + or - in that case)

f) Supported AVR-types:
* ATtiny: 10, 11, 12, 13, 13A, 15, 22, 24, 25, 26, 28, 43U, 44,
45, 48, 84, 85, 88, 167, 261, 461, 861, 2313
* AT90CAN: 32, 64, 128
* AT90S: 1200, 2313, 2323, 4343, 4414, 4433, 4434, 8515, 8535
* ATmega: 8, 8A, 16, 16HVA, 16U4, 32, 32A, 32C1, 32HVB, 32M1,
32U4, 32U6, 48, 48P, 64, 64A, 88, 88P, 88PA, 103, 128,
128A, 161, 162, 163, 164P, 165, 165P, 168, 168P, 168PA,
169, 169P, 323, 324P, 324PA, 325, 325P, 328P, 329,
329P, 406, 640, 644, 644P, 645, 649, 1280, 1281, 1284P,
2560, 2561, 3250, 3250P, 3290, 3290P, 3290P, 6450,
6490, 8515, 8535
* ATXmega: 64A1, 64A3, 128A1, 128A3, 256A3, 256A3B
* AT90PWM: 2, 2B, 3, 3B, 216, 316
* AT90USB: 82, 162, 646, 647, 1286, 1287
* AT86RF401
* List of supported AVR types with gavrasm -t

g) Language versions currently supported:


* English, German, French (just copy the file avrlang_xx.pas to
avrlang.pas by overwriting it and recompile)

h) Open issues and unresolved errors:


* The def.inc-files for the ATXmega types have extra #define
directives and use, so-far undefined, strange rules. So
including these header files from ATMEL will result in error
messages. If you use the gavrasm-internal def.inc-information
(by default, no x parameter) no errors result and the correct
labels are defined.

Versions and Changes


--------------------
Latest versions at http://www.avr-asm-tutorial.net/gavrasm/index_en.html

December 2008: Version 2.2


- Added: Support for french version (thanks to Herve)
- Added: 65 additional AVR types
- Changed: The whole internal storage and processing of hardware-
specific properties of the AVRs, the def.inc files and the type-
specific internal symbols was re-worked and changed.
- Removed: The support for AVR types AT90C8534, AT90S2343, ATmega104
and ATmega603 was removed (these types are no more supported by
ATMEL - obsolete devices).
Added: SPM Z+ support.

November 2006: Version 2.1


- Corrected: Bug in CALL and JUMP opcodes
- Corrected: Recognition of illegal characters in instructions

September 2006: Version 2.0


- Corrected: Bug in handling variables with .SET

August 2006: Version 1.9


- Corrected: Recognition of already defined symbols corrected
- Corrected: Incorrect opcode of STD without displacement

July 2006: Version 1.8


- Corrected: False memory adresses of internal SRAM in some ATmega

May 2006: Version 1.7


- Corrected: ADIW/SBIW check changed
- Corrected: Re-worked the ELIF directive

December 2005: Version 1.6


- Added: Support for types AT90CAN32 and 64, ATtiny24, 44 and 84,
ATmega 644

September 2005: Version 1.5


- Corrected: Double list output in directives removed.
- Corrected: Problem with nested IF/IFDEF/IFNDEF/IFDEVICE
directives and undefined variables resolved.

July 2005: Version 1.4


- Added: Support for types AT90CAN128, ATmega329, 3290, 406,
649, 6490, AT90PWM2, 3
- Changed: Unlike in earlier versions, directives are allowed in
columns >1 and instruction may start in column 1 of a line.
- Changed: Within the D- and E-segment, now all directives are
allowed.
- Corrected: An error while working with the constant ','.
- Corrected: Device instruction did not recognize some AVR types
with longer names.
- Corrected: Port ADCSRA in ATmega8 was only recognized under its
former name.

April 2005: Version 1.3


- Corrected: EEPROM capacity of the ATmega104 and 128
- Added: Support for types ATmega 1280, 1281, 2560, 2561 and 640

March 2005: Version 1.2


- Corrected: Error in bit WGM02 of port TCCR0B in the ATtiny13
constants
- Corrected: Missing parameters in a number of instructions were
accepted without an error
- Added: Support for the new types ATtiny25, 45 and 85

January 2005: Version 1.1


- Corrected: Error in the number of warnings
- Corrected: Error in using SETGLOBAL
- Corrected: Error in using underscore in macro names
- Added: Support for using the currect program counter PC as a variable,
e.g. in RJMP PC+3 or brcc PC-2.

October 2004: Version 1.0


- Added: Support for new types ATmega325/3259/645/6450
- Changed: Complete rewriting of the directives
- Added: New directives .ERROR, .MESSAGE, .ELIF, .IFDEF and .IFNDEF
for enhanced compatibility with the ATMEL assembler
- Added: Error output to a separate error file source.err.

March 2004: Version 0.9


- Added: Support for the new types ATmega48/88/168

Febrary 2004: Version 0.8


- Corrected: Error with setting the symbol RAMEND removed
- Corrected: Some SRam settings for older ATmega types were false
- Corrected: Assembler did not run in the short error message mode
by default

October 2003: Version 0.7


- Added: Support for new type ATtiny2313
- Added: .IFDEVICE directive
- Changed: Reliability of ATtiny22 instruction set now fine

September 2003: Version 0.6


- Corrected: Error when using negative numbers in binary operations
- Corrected: Error with type checking in .DEVICE statement
- Added: def.inc include files now trigger the internal symbol defini-
tions, no error message any more, a warning is given and the def.inc-
file is not read
- Changed: Complete instruction set reworked
- Added: Several older device types, warning for undocumented types
- Added: Nested .IF, .ELSE and .ENDIF directives

August 2003: Version 0.5


- Corrected: LD/ST instruction for type AT90S1200 added,
resulted in an error message in previous versions

July 2003: Version 0.4


- Corrected: Misleading error message when using an undefined
register
- Added: DEVICE now adds all predefined symbols, as listed in
the data sheet of the respective processor (these were
previously provided by def.inc-files). Attempting to include
a *def.inc-file results in an error message!
- Added: Support for the new type AVRtiny13 (even before ATMEL
has released its def.inc!)

June 2003: Version 0.3


- Corrected: Detection of double labels improved (ran into
internal compiler error)
- Corrected: Constant expressions starting and ending with a
bracket lead to a strange error message, therefore removed
the support for macro calls with parameters in brackets

May 2003: Version 0.2


- Added: SETGLOBAL directive for export of local symbols in
macros
- Added: Wrap-around allowed in relative jumps/calls. Wrap is
also possible in relative (conditional) branches (BRCC etc.),
difference to the ATMEL assembler!
- Fixed: Addressing in hex-file now compatible with Studio/Wavrasm
(byte-oriented, not word-oriented, also handles multiple .ORG
directives correct
- Fixed: LSL and LSR instruction for AT90S1200 are valid, invalid
error message in version 0.1
- Fixed: Labels, variables and symbols starting with an underscore
are now accepted
- Fixed: Double division x/y/z yielded false result, corrected
- Fixed: Instructions starting in column 1 of a line produced a
misleading error message, added hint
- Fixed: directives that don't start in column 1 of the line but are
preceded by a label were not recognized, error message added
- Added: Command line option E for shorter (default) or longer
error messages

December 2002: Version 0.1 Beta (first release)

Terms of use of this software


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

- Copyright for all versions: (C)2002..2005 by Gerhard Schmidt


- Free use of the source code and the compiled versions for non-
commercial purposes. Distribution allowed if the copyright
information is included.
- No warranty for correct functioning of the software.
- Report errors (especially any compiler errors) and your
most-wanted features to gavrasm@avr-asm-tutorial.net (Subject
"gavrasm 2.2"). If errors occur, please include the source code,
any include files, the list and the error file.

http://www.avr-asm-tutorial.net/gavrasm/v22/ReadMe.Txt1/20/2009 7:29:48 PM
Introduction to gavrasm AVR Assembler

Pfad: Home => AVR-Assembler gavrasm => Introduction

Introduction to Gerd's AVR Assembler


Here I introduce some special features of the gavrasm Assembler. These examples do not compile on other
assemblers. The features discussed:

1. Calling the assembler on a command line


2. Calling the assembler within a batch or a shell
3. Window caller as assembling tool
4. Using the IF-ELSE-ENDIF directive
5. Use of the EXIT directive
6. Using macro labels
7. Using special literal constants
8. Using a separator in constants

Calling the assembler on the command line


Assembling with gavrasm on the command line is as follows.

1. Open a command line (Win: select start/programs/addons/MSDOS window) or a shell (Linux-KDE) and
change the directory, typing cd [path], to the one that has the source code file.
2. Assembling starts with typing [gavrasm-path]gavrasm [-options] sourcefile[.asm].

If you have all used INCLUDE-files in the same directory where the source code file resides, you can just add
the name of these files (e.g. .INCLUDE "8515def.inc"). Otherwise add the whole path to the included files (e.g. .
INCLUDE "C:\avrtools\appnotes\8515def.inc" or "/home/gerd/avrasm/def/8515def.inc").

The parameter options are completely listed in the file ReadMe.Txt. Here are some additional explanations:

● Option -a makes sense in Linux, if you have no ANSI chars in your command line shell or if you do not
like displaying line numbers in that shell. -a switches the output of linenumbers off (as is default in the
win version of the assembler).
● Option -b makes sense for beginners to get extended error messages. The error message then comments
the required parameters of an instruction. This works only if you have chosen longer error messages with
the -e option (e.g. -eb).
● Option -l switches the generation of the list file off. That makes sense only if you don't have enough disk
space.
● Option -q suppresses the output of error messages on the command line. The only messages then are
INCLUDEs, the pass information and the result of the compilation (number of errors).
● Option -s switches the output of the symbol list in the list file on, as far as listing is not switched off. All
symbols are displayed at the end of the list file, sorted by the type of the symbol:
❍ R: Register,

❍ L: Label,

❍ C: EQU-constant,

❍ V: SET-variable,

❍ M: Local macro-symbol (label in a macro),

❍ G: Globalized macro-label

Additional informations listed are how often the symbol was redefined (nDef), how often the symbol is
used (nUsed) and the last value of then symbol in decimal and hex form.
● Option -w allows wrap-around. These are jumps or branches forward (over the end of the adress space to
its beginning) or backward (over the beginning of the adress space at its end. This option makes sense, if
the AVR has a 4k flash, which isn't accessible by relative jumps or branches. Wrap-Around in gavrasm
does also work with the relative brach instructions like BRCC or BREQ. Because other assemblers do not
allow this, this source code will only compile correct with gavrasm.
● The options -?, -h, -d and -t will set the assembler to only output the required information (-? and -h: list
of options; -d: list of implemented directives; -t: valid AVR types and their properties). An added source
code file name on the command line is ignored!

To the top of that page

Calling the assembler in a batch or a shell


If you're tired of typing in the path of the assembler, you can place that call in a batch file. If win is used: create a
new textfile in the same directory, where your source resides, and add the following lines:

REM Batch calling assembler


[drive]:
CD [Path-to-your-sourcefile]
[gavrasm-path]\gavrasm [-options] sourcefile[.asm]
PAUSE

Rename this text file with the extension ".bat". If you like, you can place a reference to that batch file on your
desktop. Assembling is just started by clicking on that file or its reference. PAUSE leaves the window open, until
you type in a character.

In Linux we use the follwing shell script:

cd [Path-to-your-sourcefile]
[Path-to-gavrasm]/gavrasm [-options] sourcefile[.asm]
read key

and place it somewhere with the extension .sh. Those who like it: place a reference to that shell on the KDE
desktop (Create new, reference to program, execute in a terminal program). The line with "read key" leaves the
shell open.

To the top of that page

Window caller - a tool for assembling


Tired of writing batch files for the command line assembler, if you work in a window-orientated environment?
Here's something for you!
By request I designed a windows program that creates batch files, calls the assembler, and allows views/editing
for the different textfiles that play a role in assembling. Some new features are:

● It is menue-driven and allows working with whole projects.


● Settings can be saved and loaded, for a quick change of the project.
● It includes an editor for the source files.
● In its current form the editor displays row and column information (unlike most simple windows editors)
and allows tab characters in the files.
● Recognizes any include files automatically and allows editing. Includes can be nested, a maximum of five
include files can be handled.
● If you open the list file after assembling, you can quickly find errors, load the responsible files and edit
the line directly.

The Read-Me file has more informations on its features and how to work with that small helper.
This executable is only available for windows operating systems (sorry linuxers). The zipped executable and the
ReadMe-file is available for downloaded here.

Use of IF-ELSE-ENDIF
The additional directives .IF, .ELSE and .ENDIF add the opportunity to compile or not compile certain code
depending on conditions. During compilation the IF condition is checked. If it is true, the following source code
is compiled. If not, the compilation is restarted behind the .ELSE or the .ENDIF directive. Be careful: If those
two directives are missing, the whole remaining source code might not be compiled!

As application example the following source code:

.EQU clock=40000000
.IF clock>4000000
.EQU divider=4
.ELSE
.EQU divider=2
.ENDIF

A short look to the symbol list in the list file shows, that divider has been set to 2. If you change the value of
clock e.g. to 10,000,000, divider will be set to 4. Generally speaking: you can avoid further changes in the source
code, if you anticipate these changes under certain conditions.

A typical application is, if you like to write and use the same code for different processor types. With other types,
interrupt vectors are different. Using .IF, the vector area of the processor is compiled specifically for each AVR
type.

;
; Define processor type on top of the source code
;
.EQU aType=2313 ; Processor is a 2313
;.EQU aType=2323 ; Processor would be a 2323
;.EQU aType=8515 ; Processor would be a 8515
;
; Int-Vector area
;
.CSEG
.ORG $0000
rjmp Main ; for all types
rjmp IntVecInt0 ; External Int Vector, is used
; Int-Vector area for 2313
.IF aType == 2313
reti ; IntVecInt1 ; External Int Vector, not used
reti ; Timer1Capt, not used
reti ; Timer1/Comp, not used
reti ; Timer1/Ovf, not used
rjmp IntVecTC0Ovf ; TC0-Overflow, used
reti ; UartRX, not used
reti ; UartUdre, not used
reti ; UartTx, not used
.ENDIF
; Int-Vector area for 2323
.IF aType == 2323
rjmp IntVecTC0Ovf ; TC0-Overflow, used
.ENDIF
; Int-Vector area for 8515
.IF aType == 8515
reti ; IntVecInt1 ; External Int Vector, not used
reti ; Timer1Capt, not used
reti ; Timer1/CompA, not used
reti ; Timer1/CompB, not used
reti ; Timer1/Ovf, not used
rjmp IntVecTC0Ovf ; TC0-Overflow, used
reti ; SpiStc, not used
reti ; UartRX, not used
reti ; UartUdre, not used
reti ; UartTx, not used
reti ; AnaComp, not used
.ENDIF
;
; Interrupt-Service-Routine INT0
;
IntVecInt0:
[...]
reti
;
; Interrupt-Service-Routine TC0-Overflow
;
IntVecTC0Ovf:
[...]
reti
;
; Main program start
;
Main:
[...]

You see, that just changing the processor type is easy, if you have once designed the vector area for this type.
Otherwise you'd have to go through your whole source code and redesign. If you forget the difference in the int
vector area, you run into a real nice design bug.

The conditions of the .IF directive can be more complex, if you like, e.g.:

.IF (aType == 2313) || (aType == 8515)

Nested .IF directives are currently not implemented in order to keep the thing simple.

To the top of that page

Use of the EXIT directive


If a certain number exceeds its defined value range, one likes to stop assembling and issuing an error message.
So, if you missed this opportunity for extended range check in other assemblers, you'll be a friend of gavrasm. .
EXIT checks the following condition and stops assembling, if it's true:

.EQU clock=4000000
.EQU divider=64
.EXIT (clock/divider)>65535

With this range check you make sure that no overflow of your 16-bit timer/counter will occur, before you run
into a debugger problem. gavrasm notifies you of such a condition and refuses compilation of the buggy code.

To the top of that page

Use of macros
Macros are code sequences stored by the assembler, which are only added to the code, if the macro is called. E.
g.:

.MACRO mtest
.nop
.ENDM
;
; Here we place the macro's code
;
mtest

The code within the macro can be changed by calling the macro with paqrameters. Parameters can be numbers,
but can also be register names or any other symbol. The parameters are referenced within the macro as @0 bis
@9. E.g. like this:

;
; Register global definition
;
.DEF rmp,R16
; Here's the macro
.MACRO mtest
ldi @0,@1 ; Expects a register as first param, a constant as second
clr @0
.ENDM
;
; Macro call with parameters
;
mtest rmp,50

The use of macros in gavrasm is enhanced, because you can call macros within a macro whenever you need it.
Nesting of macros is only limited by memory storage space.
Labels in macros are in gavrasm clearly protected. Labels can only be used within the macro, using them outside
the macro yields an error message. This prevents bugs, if you call a macro more than one time in your source
code. Globally defined symbols are accessible within the macro, so don't try to use a symbol name in a macro,
that is already defined outside. If you'd like to export a local label within a macro to the outside, use the special
directive

.SETGLOBAL label1[, label2, ...]

to export its value. Whenever you call such a macro, the value of label1 is redefined to its current value. This
works exact, even if the label is used before it is defined.

With this instrument I added the opportunity to write extensive code for different purposes in macros, and place
these code sequences into the source whenever it is required. As the code is only placed there if the macro is
called, you can include all your favoured macros, without wasting place if you don't need some of them.

To the top of that page

Use of special literal constants


gavrasm allows the use of ASCII control codes within a literal constant, e.g.

.DB "This is the first line.\m\jThis is the second line."

A '\'-char is inserted by two backspaces, e.g. "path is C:\\dos". Contrary to other assemblers, a ';' in a string is
recognized and treated correct.

To the top of that page

Separators in binary- and hex-constants


gavrasm allows the use of the dot as separator in constants, e.g.

.EQU abc = 0b0001.0010


.EQU def = 0x0FFF.FFFF

Don't ever try to assemble this code with another assembler!

To the top of that page

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gavrasm/GAVRASMI.html1/20/2009 7:29:50 PM
http://www.avr-asm-tutorial.net/gavrasm/gavrasmw/ReadMe.txt

Program GAVRASMW
----------------

Gerd's little helper to assemble AVR assembler source files


with the command-line assembler GAVRASM in a window-oriented
environment.

Freeware for Windows, last changed October 2004


Free download at
http://www.avr-asm-tutorial.net/gavrasm/GAVRASMI.html#caller

Features:
- Creates convenient batch files for calling the assembler.
- Once configured, all necessary informations are stored
in a project file, and assembling is just a one-click task.
- Configuration of parameters for assembling is included.
- View the list file output and the created batch files.
- Edit your assembler source file and any include files
(the editor displays line- and column information for
convenient error editing).
- If you view the list file, and if it reports any errors,
you can easily open the source/include file and correct
the code on the erroneous line.

Installation:
- Unpack the zip-archive to a directory, where you have
write-access-rights to.
- Place a reference to the exe-file on the desktop or in
the start menue.

Start a new project:


- Start gavrasmw.
- Select "Setup" from the menue.
In the "gavrasm" section, push "Select" and navigate to the
gavrasm.exe executable. Select the desired command-line
parameters for the assembler.
In the "Source Code File" section push "Select", navigate
to the desired path (create a new directory, if so desired)
and give the source file a name.
Either push "Save as default" or "Save as Project File" (or
both). If you save the informations as a new project file,
give the project a name.
Push the "Close" button.
- Select "Edit" and "Source" from the menue. The editor
window opens with a standard assembler source code frame.
Type in your source code, select "File" and "Save".
- If you have a line with an include directive in your source
file, and if the include file is not a "*def.inc" file, you
can edit the include file by selecting "Edit" and the
appropriate include file. If that include file does not yet
exist, it opens with a standard file header. Include files
can be nested, a maximum of five include files can be
handled in this version.
- Select "Assemble" from the main window to start the
assembler in a command line window. Actually, this creates
a batch file and starts it.
- View the list or error output of the assembler by selecting
"View" and "Listfile" or "Errorfile". If there are errors
reported, use "Error" and "FindNext" to display the error
lines. If you're at such a line, select "Error" and "Open
file" to open that file in a new window. The cursor will be
in the line where this error occurred. Correct it, save the
file and close this window. Proceed with the next error, if
any.
- View the batch file content by selecting "View" and
"Batchfile". Any changes to that file, with an external
editor, will be overwritten by the next "Assemble"
operation!

Start an existing project:


- Start gavrasmw.
- Select "Setup". If you'd like to work with other than the
default settings, select "Load Project File" and navigate
to the desired project settings file (*.asw).

Report any bugs in this software to info@avr-asm-tutorial.net


with the subject "gavrasm-caller, October version".

http://www.avr-asm-tutorial.net/gavrasm/gavrasmw/ReadMe.txt1/20/2009 7:29:52 PM
Mail form AVR-Assembler-Tutorial

Tutorial-Home ==> gavrasm-Home-EN/DE => Mailform

Inform me about new versions of gavrasm by mail


By filling this form and sending it to me via EMail, you will be notified by EMail whenever a new version of
gavrasm is released. Traffic will be about once every three monthes. Note that gavrasm is strictly private and non-
commercial, your EMail address will only be used for this purpose, and will not be given to somebody else. Your
EMail address will also not be visible to other persons receiving these mails.

Informieren Sie mich über neue Versionen von


gavrasm per Mail
Durch Ausfüllen des Formblattes und Versenden per EMail werden sie per Mail benachrichtigt, wann immer
eine neue Version von gavrasm verfügbar ist. Das ist etwa alle drei Monate der Fall. Beachten sie, dass gavrasm
strikt privat und nicht-kommerziell ist, ihre EMail-Adresse nur für diesen Zweck verwendet wird und nicht an
irgendjemanden anderen weiter gegeben wird. Auch die anderen Empfänger dieser Mails werden ihre Mail-
Adresse nicht sehen.

Your Name/Ihr Name:

Your Prename/Ihr Vorname:

Your Mail-address/Ihre EMail-Adresse:

Select your language/Sprachauswahl:


English Deutsch

mail to webmaster/Mail an Webmaster

Back to the index page.


Zurück zur Index-Seite.

http://www.avr-asm-tutorial.net/gavrasm/mailform.html1/20/2009 7:29:55 PM
http://www.avr-asm-tutorial.net/gavrasm/v22/LiesMich.Txt

Programm gavrasm

AVR Assembler fuer ATMEL AVR-Prozessoren


========================================

Kommandozeilen Assembler fuer ATMEL AVR-Prozessoren der Typenreihen


- AT90S,
- AT90CAN,
- AT90USB,
- ATtiny,
- ATmega, und
- ATXmega.

Fuer Linux i386 compilierte ausfuehrbare Datei: gavrasm


Fuer Dos bzw. Win32 compilierte ausfuehrbare Datei: gavrasm.exe
Quellcode in fpc-Pascal

Aufrufe und Optionen


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

Aufruf: gavrasm [-abelmqsw] quelldatei[.asm]


Parameter:
a: Ausgabe von ANSI-Zeichen umschalten (An/Aus)
Default ist An (Linux) bzw. Aus (Dos, Win)
b: Erweiterte Syntaxkommentierung fuer Anfaenger (nur bei e!)
Default ist Aus (kein zusaetzlicher Kommentar)
e: Laengeres, ausfuehrlicheres Format fuer Fehlermeldungen
Default ist Aus (kurze Fehlermeldungen)
l: Ausgabe der LIST-Datei unterdruecken
Default ist LIST-Datei-Ausgabe an
m: Expansion von Makros nicht listen
Default ist List ein
q: Keine Ausgabe von Meldungen auf der Kommandozeile (quiet)
Ausnahme: Erzwungene Meldungen (.MESSAGE)
Default ist Ausgabe eingeschaltet
s: Ausgabe der Liste der Symbole im Listing an
Default ist keine Symbolliste
w: Ermoegliche Wrap-around
Default ist Wrap-Around ausgeschaltet
x: Benutze nicht die internen def.inc-Informationen
Default ist die Verwendung interner def.inc-Informationen
Ausgabedateien:
quelldatei.lst ... Assembler-Listing, Textdatei
quelldatei.hex ... Code im Format Intel-Hex, Textdatei
quelldatei.eep ... EEPROM-Inhalt im Format Intel-Hex, Textdatei
(Datei wird wieder gelöscht, wenn kein .ESEG-
Inhalt erzeugt wurde)
quelldatei.err ... Fehlermeldungen falls zutreffend, Textdatei

Aufruf: gavrasm [-?hdt]


Parameter:
?: Liste der Optionen
h: Liste der Optionen
d: Liste der unterstuetzten Direktiven
t: Liste der unterstuetzten AVRTypen

Erlaeuterung zur A-Option:


Unter Linux ist die Ausgabe von ANSI-Codesequenzen per
Default eingeschaltet, bei anderen OS abgeschaltet. Mit der
A-Option wird diese Voreinstellung bei allen Betriebs-
systemen invertiert.

Eigenschaften des Assemblers


----------------------------
Im folgenden sind nur die Besonderheiten dieses Assemblers
beschrieben. In der Regel ist dieser Assembler kompatibel mit
anderen AVR-Assemblern (z.B. dem ATMEL(R)-Assembler).

a) Unterschiede dieses Assemblers, die zu Fehlermeldungen und


Warnungen bei Code fuehren, der unter anderen Assemblern
fehlerfrei assembliert wird
* Die Header-Dateien von ATMEL(R), die die Symbole des ver-
wendeten AVR-Typs enthalten, koennen mit der .INCLUDE-
Direktive angegeben werden. Die Angaben zu der Datei
werden aber in der Default-Einstellung von gavrasm ignoriert,
die Datei wird nicht gelesen. Stattdessen wird aus dem
angegebenen Dateinamen der AVR-Typ extrahiert und die intern
im gavrasm gespeicherten Symbole fuer diesen Typ gesetzt.
Dies sollte man beachten fuer den Fall, dass die Header-
Dateien vom User manuell geaendert oder ergaenzt wurden.
gavrasm ignoriert wegen dieses Verhaltens die in der
Headerdatei vorgenommenen Aenderungen.
Im Gegensatz zu anderen Assemblern werden die Symbole
des betreffenden Typs bereits mit der DEVICE-Direktive
festgelegt, ein Einlesen von Header-Dateien ist ueber-
fluessig. Die Headerdatei muss auch nicht vorhanden sein.
Diese Automatik kann umgangen werden, indem der Namens-
bestandteil "def.inc" der Headerdatei veraendert wird und
damit die Erkennung der Headerdatei unterbunden wird.
Ab Version 2.3 kann diese Eigenschaft auch einfach mit dem
Schalter x abgeschaltet werden. Die Angabe von x auf der
Kommandozeile führt dazu, dass alle Include-Dateien
ausgewertet werden.
* Dateinamen (z.B. in der INCLUDE-Direktive) muessen nicht
in Gaensefueszen angegeben werden. Dies gilt nicht fuer die
Linux-Version, hier muessen Dateinamen in Gaensefueszen ein-
geschlossen werden ("...").
* Absolutwerte z.B. bei Sprungdistanzen werden bereits dann
erkannt, wenn die Sprungdistanz durch ein Vorzeichen
eingeleitet wird, wie z.B. " brcc +10". Die Verwendung der
Schreibweise PC+10 ist optional.
* Ein wichtiger Unterschied zu anderen Assemblern ist bei
gavrasm die Verarbeitung von Texten. Die Verwendung dieser
Features bedingt gegebenenfalls Inkompatibilitaet des Quell-
codes zu anderen Assemblern. Die Unterschiede im Einzelnen:
- In Textpassagen kann ein doppeltes Anfuehrungszeichen ""
verwendet werden, um ein Anfuehrungszeichen in den Text
einzufuegen. Andere Assembler quittieren dies mit "garbage
at end of line" und ignorieren den Text nach dem doppel-
ten Anfuehrungszeichen.
- Beim Auftreten des Semikolons ; in einer ASCII-Konstante
(';') oder einem Text ("...;...") bemaengeln andere As-
sembler dies mit einer Fehlermeldung, da das Semikolon
faelschlich als Kommentarzeichen interpretiert wird. In
gavrasm ist das Semikolon in Konstanten und Texten zu-
laessig und wird korrekt verarbeitet.
- Beim Einfuegen von nicht druckbaren ASCII-Steuerzeichen
in Texte mittels \ (z.B. "...\m\j\@") interpretieren
andere Assembler dieses Steuerzeichen nicht wie gavrasm.
Diese uebersetzen \ stattdessen als ASCII-Zeichen. Nur
bei einer ungeradzahligen Anzahl macht sich dies mit
einer Warnung bemerkbar, die Anzahl Zeichen in der Text-
konstante sei ungerade und es werde ein Nullzeichen ein-
gefuegt.
* Die .ERROR-Direktive verlangt bei gavrasm einen Text als
Parameter, bei dem ATMEL-Assembler nicht. Der Text macht
Sinn, weil man ja wissen moechte, was genau den Error ver-
ursacht hat. Beim ATMEL-Assembler ist dazu eine zusaetzli-
che .MESSAGE-Direktive notwendig.

b) Verfuegbarer Quellcode:
* FPK-Pascal, fuer Linux(i386), DOS (go32v2) und Win32
Zum Kompilieren die neuesten Versionen des Compilers verwenden,
aeltere Versionen haben Probleme mit einigen Pascal-Instruktionen
(FPK-Compiler ueber http://www.freepascal.org erhaeltlich).
Die zahlreichen Warnungen beim Kompilieren koennen ignoriert
werden.
* Dateien:
gavrasm.pas: Hauptdatei
gavrdev.pas: Unit mit allen Hardware-Eigenschaften und
vordefinierten Symbolen der unterstuetzten
AVR-Typen (ersetzt alle bekannten *def.inc
Dateien)
gavrif.pas: Unit zur Implementierung geschachtelter
IF/ELSE/ELIF/ENDIF-Konstruktionen
gavrlang.pas: Unit zur Sprachauswahl (deutsch, englisch und
franzoesisch verfuegbar: gavrlang_de.pas,
gavrlang_en.pas, gavrlang_fr.pas), deutsche
Version durch Kopieren von gavrlang_de.pas,
Einfuegen als gavrlang.pas und compilieren.
gavrline.pas: Unit zum Splitten der asm-Zeilen in ihre
Bestandteile
gavrmacr.pas: Unit fuer die Makro-Verwaltung
gavrout.pas: Unit fuer die Hexausgabe
gavrsymb.pas: Unit fuer die Symbole-Verwaltung
* Vor dem Kompilieren die gewuenschte Sprachdatei (gavrlang_de.pas)
kopieren und als gavrlang.pas umbenennen!
* Testdatei zur Ueberpruefung des Assemblers:
instr.asm: Testdatei mit allen AVR-Instruktionen
testdir.asm: Testdatei mit allen Direktiven des Assemblers

c) Direktiven:
* DEVICE-Direktive bindet automatisch alle Symbole des
betreffenden AVR-Typs ein, das Include von *def.inc-Dateien
ist damit jetzt ueberfluessig.
* Die EXIT-Direktive ohne Bedingung bricht die weitere
Verarbeitung der Quelldatei ab und ist kompatibel mit
anderen AVR-Assemblern. Zusaetzlich kann aber auch eine
Bedingung als Parameter angegeben werden. Ist die Bedin-
gung erfuellt (TRUE, 1), dann bricht gavrasm den gesamten
Assembliervorgang hier ab. Dies funktioniert auch in
INCLUDE-Dateien.
Dieses Feature kann verwendet werden, um z.B. Bereichs-
pruefungen waehrend der Assemblierung durchzufuehren und
bei Ueber- oder Unterschreitung bestimmter Grenzen mit einer
entsprechenden Fehlermeldung abzubrechen.
Diese Direktive kann teilweise durch die .ERROR-Direktive er-
setzt werden. Die .ERROR-Direktive bricht die weitere Assem-
blierung nicht ab.
* Zusaetzliche .IF, .ELSE, ELIF und .ENDIF Direktiven: Code
nach .IF (Bedingung) wird nur assembliert, wenn die Bedingung
wahr (1) ist, sonst wird zum Code nach der .ELSE-, .ELIF
oder .ENDIF-Direktive verzweigt. Mit .ELIF kann im Unterschied
zu .ELSE eine zusaetzliche Bedingung abgefragt werden. Bitte
die ELIF-Direktive nur alternativ zu ELSE verwenden, eine ge-
mischte Verwendung ist nicht definiert!
Beliebig tief verschachtelte .IF, .ELSE/ELIF und .ENDIF
Direktiven sind zulaessig.
* .IFDEVICE ermoeglicht Verzweigungen abhaengig vom AVR-Typ,
andernfalls wird nach .ELSE, .ELIF oder .ENDIF weiter
assembliert.
* .IFDEF und .IFNDEF Direktive zur Abfrage, ob ein Symbol
definiert ist oder nicht. Die Definition des Symbols MUSS
vor der ersten Abfrage erfolgen, andernfalls resultieren
Uebersetzungsfehler!
* .MESSAGE gibt eine erzwungene Meldung (in "..." als Parameter)
aus und kann zur Benachrichtigung waehrend des Uebersetzens
verwendet werden.
* .ERROR erzwingt einen Fehler mit einem definierbaren Fehler-
text (in "..." als Parameter).
* Zusaetzliche Direktive .SETGLOBAL p1,p2,[...] zum Export lo-
kaler Symbole aus Makros. Normalerweise sind Symbole (Labels)
in Makros lokal, d.h. auszerhalb des Makros nicht verwendbar.
SETGLOBAL stellt die gelisteten Symbole auch auszerhalb zur
Verfuegung. Vorsicht bei der Anwendung dieses Features, es
kann zu Fehlern fuehren.
* Rekursive .INCLUDE-Direktive mit beliebig tiefer Schachtelung,
In der Linux-Version Dateiname auf jeden Fall in Gaensefuesze
einschlieszen!
* Die Liste der unterstuetzten Direktiven wird durch Aufruf mit
gavrasm -d ausgegeben.

d) Makros:
* Erweiterte Makro-Aufrufe:
- verschachtelte Aufrufe ohne Begrenzung zulaessig
- erweiterte Parameterueberpruefung bereits innerhalb der
Definition, nicht erst beim Aufruf
- alle Labels in Makros sind lokal definiert und von auszerhalb
des Makros zwecks verbesserter Fehlererkennung unzugaenglich
- Export lokaler Symbole mit der .SETGLOBAL-Direktive
- Labels in Makros sind auch vorwaerts und bei verschachtelten
Makrodefinitionen gueltig
- Optionale Verwendung von .ENDM oder .ENDMACRO zum Abschluss
des Makros
- Liste aller definierten und verwendeten Makros im Listing,
wenn die Ausgabe der Symbolliste eingeschaltet ist (Aufruf
mit Option -s und ohne Option -l bzw. mit .LIST im Quellcode

d) Fehlererkennung und Syntaxpruefung:


* Erweiterte Symbolpruefung auf Zulaessigkeit:
- exakte Unterscheidung nach Symboltypen (Typen: R fuer Register,
C fuer Konstanten, V fuer Variablen, T fuer AVR-Typ-
Definitionen, M fuer lokale Makro-Sprungmarken, L fuer
Sprungmarken, G fuer globalisierte Lokalvariablen in Makros)
- erweitert kompatibel mit den meisten gaengigen ATMEL-Header-
Dateien (akzeptiert OR und BRTS als Symbolname, weil diese in
aelteren *def.inc-Dateien von ATMEL(R) verwendet wurden)
- erweiterte Erkennung undefinierter Symbole, keine Default-
Setzung auf Null
* Erweiterte Fehlerkommentierung und Warnungen ( mehr als 100
Fehlertypen, 8 Warnungstypen)
* Ausfuehrliche Syntaxdarstellung im Anfaengermodus (Option -eb)
zu fehlerhaften Instruktionen und Direktiven in der Listdatei
* Erweiterte Rechenpruefung (Ueber-, Unterlauf von Rechenschritten
bei internen 32-Bit-Integerwerten)
* Erweiterte zulaessige Zeichen in Literalkonstanten: ';', '''',
'\n', '\\', "abc\n\j", "abc;def"
* Zulaessiges Trennzeichen (Punkt, '.') in Binaer- und Hexadezimal-
zahlen fuer verbesserte Lesbarkeit des Quellcodes (z.B.
0b0001.0010, $124A.035F, 0x82.FABC)
* BYTE1-Funktion (analog zu BYTE2 etc.)
* Ermoeglicht bei relativen Spruengen die Angabe des
Displacements, z.B. rjmp +10 oder brcc -3 (Displacement MUSS
in diesem Fall mit einem Vorzeichen beginnen)

e) Unterstuetzte AVR-Typen:
* ATtiny: 11, 12, 13, 15, 22, 24, 25, 26, 28, 43U, 44, 45, 48,
84, 85, 88, 167, 261, 461, 861, 2313
* AT90CAN: 32, 64, 128
* AT90S: 1200, 2313, 2323, 4343, 4414, 4433, 4434, 8515, 8535
* ATmega: 8, 16, 16HVA, 32, 32U4, 32M1, 32C1, 48, 48P, 64, 83,
88, 88P, 103, 128, 161, 162, 163, 164P, 165, 165P,
168, 168P, 169, 169P, 323, 324P, 325, 325P, 328P, 329,
329P, 406, 640, 644, 644P, 645, 649, 1280, 1281, 1284P,
2560, 2561, 3250, 3290, 3250P, 3290, 3290P, 6450,
6490, 8515, 8535
* ATXmega: 64A1, 128A1 (siehe offene Punkte!)
* AT90PWM: 2, 2B, 3, 3B, 216, 316
* AT90USB: 162, 646, 647, 1286, 1287
* AT86RF401
* Liste der unterstuetzten AVR-Typen durch Aufruf mit gavrasm -t

f) Sprachversionen:
* Deutsche, englische und franzoesische Sprachversion verfuegbar

g) Offene Punkte und bekannte Fehler:


* Mit den ATXmega Typen hat ATMEL #DEFINE-Anweisungen in die
Headerdateien eingefuehrt. Deren Format ist nicht definiert.
Diese Defines werden von gavrasm als Symbole definiert und
können verwendet werden.

Versionen und Aenderungen


-------------------------
Neueste Versionen unter
http://www.avr-asm-tutorial.net/gavrasm/index_de.html

Dezember 2008: Version 2.2


- Hinzugefuegt: Unterstuetzung fuer franzoesische Sprachversion
(danke an Herve)
- Hinzugefuegt: 50 neue AVR-Typen
- Geaendert: Die gesamte interne Speicherung und Verarbeitung der
Hardware-Eigenschaften der AVR, der def.inc-Dateien und der
prozessorspezifischen internen Symbole wurde ueberarbeitet und
geaendert.
- Entfernt: AVR-Typen AT90C8534, AT90S2343, ATmega104, ATmega603,
(die entfernten Typen werden von ATMEL nicht mehr supported -
obsolet)
-Hinzugefuegt: SPM Z+ Unterstuetzung

November 2006: Version 2.1


- Korrigiert: Fehler beim Opcode von CALL und JUMP
- Korrigiert: Erkennung von ungueltigen Zeichen in Instruktionen

September 2006: Version 2.0


- Korrigiert: Fehler bei der Behandlung von Variablen mit SET

August 2006: Version 1.9


- Korrigiert: Fehler bei der Erkennung benutzter Symbole
- Korrigiert: STD ohne Displacement ergab falschen Opcode

July 2006: Version 1.8


- Korrigiert: Fehler bei Memory-Adressen bei einigen ATmega

Mai 2006: Version 1.7


- Korrigiert: Pruefung der ADIW/SBIW-Instruktionen.
- Korrigiert: ELIF-Direktive ueberarbeitet.

Dezember 2005: Version 1.6


- Hinzugefuegt: Unterstuetzung fuer die AVR-Typen AT90CAN32,
AT90CAN64, ATtiny24, 44, 84, ATmega644.

September 2005: Version 1.5


- Korrigiert: Doppelte Ausgabe von Direktiven beseitigt.
- Korrigiert: Problem mit geschachtelten IF/IFDEF/IFNDEF/IFDEVICE
Direktiven beseitigt.

Juli 2005: Version 1.4


- Hinzugefuegt: Unterstuetzung fir die AVR-Typen AT90CAN128,
ATmega329, 3290, 406, 649, 6490, AT90PWM2, 3
- Geaendert: Anders als in frueheren Versionen sind Direktiven
in allen Spalten der Zeile erlaubt, Instruktionen duerfen in
Spalte 1 der Zeile beginnen.
- Geaendert: In D- und E-Segmenten sind alle Direktiven
zulaessig.
- Korrigiert: Ein Fehler bei der Verarbeitung der Konstante
',' wurde behoben.
- Korrigiert: DEVICE Direktive erkannte einige Typen mit
laengeren Namen nicht korrekt.
- Korrigiert: Port ADCSRA bei ATmega8 wurde nur unter altem
Namen erkannt.

April 2005: Version 1.3


- Korrigiert: falsche EEPROM-Groesse bei ATmega104 und 128
- Hinzugefuegt: Unterstuetzung fuer die Typen ATmega 1280, 1281,
2560, 2561 und 640

Maerz 2005: Version 1.2


- Korrigiert: Fehler beim Registerbit WGM02 im Port TCCR0B des
ATtiny13 war falsch
- Korrigiert: Fehlende Parameter bei einer Reihe von Instruktionen
wurden faelschlicherweise ohne Kommentar akzeptiert.
- Hinzugefuegt: Unterstuetzung fuer die Typen ATtiny25, 45
und 85

Januar 2005: Version 1.1


- Korrigiert: Fehler bei der Anzahl Warnungen
- Korrigiert: Fehler bei der Verwendung von SETGLOBAL
- Korrigiert: Fehler bei der Verwendung von underscore bei
Macronamen
- Hinzugefuegt: Unterstuetzung fuer die optionale Angabe von
PC bei relativen Sprungdistanzen.

Oktober 2004: Version 1.0


- Hinzugefuegt: Unterstuetzung fuer neue Typen ATmega325/3250/
645/6450
- Geaendert: Gesamte Auswertung von Direktiven ueberarbeitet
- Hinzugefuegt: Neue Direktiven .ERROR, .MESSAGE, .ELIF, .IFDEF,
IFNDEF fuer verbesserte Kompatibilitaet mit neueren ATMEL(R)-
Assemblern
- Hinzugefuegt: Ausgabe aller Fehlermeldungen in eine separate
Fehlerdatei source.err.

Maerz 2004: Version 0.9


- Hinzugefuegt: Unterstuetzung fuer neue Typen ATmega48/88/168

Februar 2004: Version 0.8


- Korrigiert: Fehler beim Setzen des RAMEND-Symbols beseitigt
- Korrigiert: Falsche SRam-Angaben bei drei aelteren ATmega-Typen
- Korrigiert: Assembler startete nicht mit kurzen Fehlermeldungen
als Voreinstellung, wenn keine Parameter angegeben wurden

Oktober 2003: Version 0.7


- Hinzugefuegt: Unterstuetzung fuer neuen Typ ATtiny2313
- Hinzugefuegt: Direktive .IFDEVICE fuer Verzweigungen abhaengig
vom AVR-Typ
- Geaendert: Einstufung von ATtiny22 als zuverlaessig, da
jetzt Datenblatt verfuegbar

September 2003: Version 0.6


- Korrigiert: Fehler bei der Verarbeitung negativer Zahlen in
Funktionen behoben
- Korrigiert: Fehler bei der Verarbeitung von .DEVICE behoben
- Geaendert: Der Aufruf von def.inc-Dateien mit .INCLUDE bewirkt
jetzt, dass die entsprechenden internen Symbol-Definitionen
geladen werden und eine Warnung ausgegeben wird, die
def.inc-Datei wird nicht verarbeitet
- Geaendert: Gesamten Instruktionsset ueberarbeitet
- Hinzugefuegt: Support fuer einige aeltere Typen, Warnung bei
undokumentierten Typen
- Hinzugefuegt: Verschachtelte IF-Konstruktionen

August 2003: Version 0.5


- Korrigiert: LD/ST-Instruktion fuer AT90S1200 zulaessig, ergab
Fehlermeldung!

Juli 2003: Version 0.4


- Korrigiert: Missverstaendliche Fehlermeldung bei der Verwendung
undefinierter Registersymbole
- Hinzugefuegt: DEVICE-Direktive bindet alle Symbole des betref-
fenden AVR-Typs ein und ersetzt die *def.inc-Dateien. Ausgabe
einer Fehlermeldung beim INCLUDE von *def.inc-Dateien!
- Unterstuetzung fuer den neuen Typ ATtiny13.

Juni 2003: Version 0.3


- Korrigiert: Erkennung doppelter Marken korrigiert (ergab
faelschlich internen Compiler-Fehler)
- Korrigiert: Konstantenausdruecke, die mit einer Klammer beginnen
und enden, wurden nicht richtig erkannt. Daher Unterstuetzung
fuer Makro-Aufrufe mit geklammerten Parametern entfernt!

Mai 2003: Version 0.2


- Hinzugefuegt: Export lokaler Makrosymbole nach global
implementiert
- Wrap-Around bei relativen Verzweigungen/Spruengen implementiert,
funktioniert bei allen Verzweigungsinstruktionen (RJMP, RCALL)
und bei allen bedingten Branch-Instruktionen (Unterschied zu
aelteren ATMEL-Assemblern!)
- Korrigiert: Mit Studio/Wavrasm kompatible Adressierung in der
Hex-Datei (byte-orientiert, nicht wort-orientiert), funktioniert
auch bei mehreren .ORG-Direktiven korrekt
- Korrigiert: Instruktionen LSL und LSR fuer Typ AT90S1200 gueltig,
ergab Fehlermeldung in Version 0.1
- Korrigiert: Marken/Variable/Konstanten mit Unterstrich als erstem
Zeichen werden jetzt akzeptiert
- Korrigiert: Doppelte Division x/y/z rechnete falsch!
- Korrigiert: Instruktionen in Spalte 1 werden nicht akzeptiert,
missverstaendliche Fehlermeldung verbessert
- Korrigiert: Direktiven nach einer Marke in der gleichen Zeile
werden ueberlesen und nicht ausgefuehrt, Fehlermeldung
hinzugefuegt
- Hinzugefuegt: Kommandozeilenoption E fuer kurze (Default-Ein-
stellung) oder laengere Fehlermeldungen

Dezember 2002: Version 0.1 Beta (Erstveroeffentlichung)

Nutzungsbedingungen
-------------------

- Copyright fuer alle Versionen:


(C)2002/2003/2004/2005/2006/2008 by Gerhard Schmidt
- Nutzung des Quellcodes und der kompilierten Versionen fuer
nichtkommerzielle Zwecke frei. Weiterverbreitung nur unter
Beibehaltung der enthaltenen Copyright-Angaben zulaessig.
- Keine Garantie fuer korrekte Funktion der Software.
- Fehlermeldungen (mit Quellcode, allen Include-Dateien und
Listfile) sowie Featurewuensche mit Betreff
"gavrasm 2.2" bitte an gavrasm@avr-asm-tutorial.net.

http://www.avr-asm-tutorial.net/gavrasm/v22/LiesMich.Txt1/20/2009 7:30:33 PM
Einführung in den gavrasm AVR Assembler

Pfad: Home => AVR-Assembler gavrasm => Einführung

Einführung in Gerd's AVR Assembler


Hier werden die besonderen Features des gavrasm-Assemblers vorgestellt. Die Beispiele compilieren nicht
unbedingt auch auf anderen Assemblern. Im einzelnen werden vorgestellt:

1. Aufruf des Assemblers auf der Kommandozeile


2. Aufruf des Assemblers mit einer Batch oder in einer Shell
3. Hilfsprogramm zum Aufruf unter Windows
4. Verwendung von IF-ELSE-ENDIF
5. Verwendung von EXIT
6. Verwendung von Makros
7. Verwendung von besonderen literalen Konstanten
8. Verwendung von Trennzeichen in Konstanten

Aufruf des Assemblers auf der Kommandozeile


Beim Aufruf in einer Kommandozeile geht man am besten so vor:

1. Man öffnet eine Kommandozeile (Win: meistens unter Start/Programme/Zubehör/Eingabeaufforderung)


oder Shell (Linux-KDE) und wechselt mit cd [Pfad] in das Verzeichnis mit dem Quelltext.
2. Das Assemblieren wird mit [gavrasm-pfad]gavrasm -optionen quelltext[.asm] gestartet.

Befinden sich alle verwendeten INCLUDE-Dateien im Pfad des Quelltextes, dann braucht man nur den Namen
der Include-Dateien (z.B. "8515def.inc") anzugeben. Andernfalls muss dem Namen der korrekte Pfad hinzugefgt
werden (z.B. "C:\avrtools\appnotes\8515def.inc" oder "/home/gerd/avrasm/def/8515def.inc").

Die Parameteroptionen sind in der Datei Liesmich.Txt generell aufgelistet. Hier einige ausführlichere
Erläuterungen:

● Die Option -a ist nur unter Linux sinnvoll zu verwenden. Sie schaltet die Ausgabe der einzelnen
Zeilennummern während des Kompiliervorganges aus.
● Die Option -b ist sinnvoll, um bei Fehlermeldungen eine ausführlichere Kommentierung der Parameter
einer Instruktion zusätzlich zu erhalten. Sie funktioniert nur, wenn gleichzeitig die Option -e gewählt wird
(z.B. -eb).
● Die Option -l schaltet die Erzeugung der List-Datei generell aus. Nur für Puristen sinnvoll, die unbedingt
knappen Plattenplatz sparen wollen.
● Die Option -q sperrt generell die Ausgabe von Meldungen auf der Kommandozeile. Die einzigen
Nachrichten sind INCLUDEs, die Pass-Information und der Erfolg/Misserfolg des Kompiliervorganges
(Anzahl Fehler).
● Die Option -s schaltet die Ausgabe der verwendeten Symbole in der List-Datei an, sofern die Listausgabe
nicht mit der Direktive .NOLIST im Quellcode ausgeschaltet ist. Alle Symbole werden am Ende der Datei
sortiert nach ihrem Typ
❍ R: Register,

❍ L: Label oder Marke,

❍ C: EQU-Konstante,

❍ V: SET-Variable,

❍ M: Lokales Makro-Symbol (Label/Marke in einem Makro),

❍ G: Globalisiertes Makro-Symbol

geordnet ausgegeben. Dabei erhält man als zusätzliche Information, wie oft das Symbol definiert wurde
(nDef, sinnvoll bei Variablen), verwendet wird (nUsed) und den letzten Wert des Symbols in dezimaler
und hexadezimaler Form.
● Die Option -w erlaubt das Wrap-Around, also Sprünge vorwärts über das Ende des Flash-
Programmspeichers hinaus (an den Anfang des Adressraums) bzw. rückwärts vor den Beginn des
Speichers (an das Ende des Adressraums). Die Option ist nur sinnvoll, wenn der AVR einen über 4k
großen Flash verfügt und damit einen sehr langen Adressraum hat, der mit relativen Sprüngen nicht mehr
direkt überbrückt werden kann. Das Wrap-Around funktioniert in gavrasm auch mit den relativen Branch-
Instruktionen (z.B. BRCC oder BREQ). Weil das andere Assembler (z.B. der ATMEL-Assembler) aber
nicht beherrschen, sind solche Quelltexte nicht mit anderen Assemblern kompilierbar!
● Die Optionen -?, -h, -d und -t veranlassen gavrasm ausschließlich zur Ausgabe der gewünschten
Informationen (-? und -h: zulässige Optionen, -d: implementierte Direktiven, -t: zulässige AVR-Typen
und deren Eigenschaften). Eine gleichzeitig angegebene Quelldatei wird dabei ignoriert und nicht
assembliert!

An den Seitenanfang

Aufruf des Assemblers mit einer Batch oder in einer Shell


Um sich die wiederholte Prozedur der Eingabe von Pfadnamen zu ersparen, kann der Assembler-Aufruf in einer
Batchdatei erfolgen. Unter Win wird dazu eine neue Textdatei erzeugt, mit folgenden Zeilen versehen

REM Batch-Aufrufdatei
[Laufwerk]:
CD [Pfad-zur-Sourcedatei]
[gavrasm-pfad]\gavrasm [-optionen] quelldatei[.asm]
PAUSE

Die Textdatei wird mit der Endung ".bat" in einem beliebigen Verzeichnis gespeichert. Wer mag, kann eine
Verknüpfung auf diese Batchdatei auf den Desktop legen. Sie kann durch Anklicken gestartet werden und steuert
den Kompilierprozess. Die Pause-Anweisung bewirkt, dass sich das Fenster erst nach einer Taste schließt.

Unter Linux schreiben wir folgendes Shell-Script:

cd [Pfad-zur-Sourcedatei]
[Pfad-zu-gavrasm]/gavrasm [-optionen] Quelldatei[.asm]
read key

und speichern es mit der Endung .sh irgendwo ab. Wer mag, kann sich eine Verknüpfung zu dieser Shelldatei auf
dem KDE-Desktop erzeugen (Neu erstellen/ Verknüpfung mit Programm, dabei Ausführung in einem
Terminalprogramm wählen) und anschließend die Ausführungrechte setzen. Die Zeile mit read key bewirkt, dass
man die Ausgabe im Terminal verfolgen kann, bevor sich das Terminal schließt.

An den Seitenanfang

Window Caller - Werkzeug für den Aufruf unter Windows


Wenn Du in einer Fensterumgebung arbeitest, könntest Du müde werden beim Schreiben von Batchdateien. Hier
ist was einfaches als Ersatz.
Auf vielfachen Wunsch habe ich ein Windows-Programm geschrieben, das menuegesteuert Batchdateien
erzeugt, den Assembler aufruft und in einem Editorfenster Dateien anzeigen kann. Einige neue Schmankerl sind:

● Die Source- und Include-Dateien lassen sich auch editieren, dabei werden Zeile und Spalte angezeigt
(anders als bei den anderen simplen Windows-Editoren).
● Der Editor arbeitet auch mit Tab-Zeichen.
● Mit Include eingebundene Dateien werden automatisch erkannt und können editiert werden. Das
funktioniert auch rekursiv mit bis zu maximal fünf Include-Dateien.
● Wird nach dem Assemblieren die List-Datei angezeigt, können Fehler im Quelltext komfortabel gesucht
werden. Auf Wunsch werden die Dateien, in denen der Fehler auftrat, in den Editor geladen und direkt die
fehlerhafte Stelle angesteuert.
● Es können jetzt beliebig viele Dateien gleichzeitig angeschaut und editiert werden.

Mehr über die Features und über die Bedienung gibt es in der Lies-Mich-Datei.
Das Programm läuft nur unter Windows (sorry, Linuxer) und steht gepackt unter diesem Link zum Download zur
Verfügung.

An den Seitenanfang

Verwendung von IF-ELSE-ENDIF


Die zusätzlichen Direktiven .IF, .ELSE und .ENDIF ermöglichen es, je nach den Einstellungen im Kopf einer
Quelldatei oder nach festgestellten Rechenergebnissen Programmteile zu kompilieren oder nicht. Die IF-
Bedingung wird während der Kompilation geprüft. Ist sie erfüllt, wird der folgende Quellcode assembliert. Wenn
nicht, wird die Kompilierung des Quellcodes erst nach der .ELSE- oder der .ENDIF-Direktive wieder fortgesetzt.
Achtung: Fehlen beide Anweisungen, wird der Rest des gesamten Quelltextes nicht mehr kompiliert!

Als Anwendungsbeispiel:

.EQU taktfrequenz=40000000
.IF taktfrequenz>4000000
.EQU teiler=4
.ELSE
.EQU teiler=2
.ENDIF

Ein Blick auf die Symbolliste zeigt, dass Teiler nach dem Kompilieren auf 2 gesetzt ist. Wird die Taktfrequenz
im Kopf z.B. auf 10.000.000 umdefiniert, wird der Teiler auf 4 gesetzt. Allgemein vermeidet man dadurch, dass
für jede Änderung von minimalen Parametern eigene Änderungen im Quelltext, außer im Kopf, vorgenommen
werden müssen.

Als typische Anwendung kann ein Quelltext z.B für verschiedene Typen von AVRs geschrieben werden. Weil
sich die Interruptvektoren bei jedem Typ an einer anderen Stelle befinden, kann der Vektorbereich spezifisch
kompiliert werden.

;
; Definiere Prozessor im Kopf
;
.EQU aTyp=2313 ; Prozessor ist ein 2313
;.EQU aTyp=2323 ; Prozessor wäre ein 2323
;.EQU aTyp=8515 ; Prozessor wäre ein 8515
;
; Abschnitt mit den Int-Vektoren
;
.CSEG
.ORG $0000
rjmp Main ; für alle Typen gleich
rjmp IntVecInt0 ; External Int Vector, wird verwendet
; Int-Vektoren für 2313
.IF aTyp == 2313
reti ; IntVecInt1 ; External Int Vector, nicht verwendet
reti ; Timer1Capt, nicht verwendet
reti ; Timer1/Comp, nicht benutzt
reti ; Timer1/Ovf, nicht benutzt
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
reti ; UartRX, nicht benutzt
reti ; UartUdre, nicht benutzt
reti ; UartTx, nicht verwendet
.ENDIF
; Int-Vektoren für 2323
.IF aTyp == 2323
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
.ENDIF
; Int-Vektoren für 8515
.IF aTyp == 8515
reti ; IntVecInt1 ; External Int Vector, nicht verwendet
reti ; Timer1Capt, nicht verwendet
reti ; Timer1/CompA, nicht benutzt
reti ; Timer1/CompB, nicht benutzt
reti ; Timer1/Ovf, nicht benutzt
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
reti ; SpiStc, nicht verwendet
reti ; UartRX, nicht benutzt
reti ; UartUdre, nicht benutzt
reti ; UartTx, nicht verwendet
reti ; AnaComp, nicht verwendet
.ENDIF
;
; Interrupt-Service-Routine INT0
;
IntVecInt0:
[...]
reti
;
; Interrupt-Service-Routine TC0-Overflow
;
IntVecTC0Ovf:
[...]
reti
;
; Hauptprogramm
;
Main:
[...]

Es ist klar ersichtlich, dass bei einer Umstellung des Quellcodes für einen anderen Prozessor alle Änderungen
sehr umfangreich und deshalb fehlerträchtig sind. Vergisst man die Sache mit den unterschiedlichen
Interruptvektoren, ergibt sich ein nettes Fehlersuch-Problem. Mit dem dargestellten Quellcode ist die Umstellung
des Programmes für einen anderen Typ ein Leichtes.

Selbstverständlich können die Bedingungen der .IF-Direktive auch komplexer formuliert sein, wie z.B. hier:

.IF (aTyp == 2313) || (aTyp == 8515)

Verschaltelte IF-Direktiven sind wegen der Unübersichtlichkeit und wegen möglicher Fehlerquellen allerdings
nicht implementiert.

An den Seitenanfang

Verwendung von EXIT


Überschreitet eine Größe einen zulässigen Wertebereich, dann bricht man die Assemblierung mit einer
Fehlermeldung gerne ab, damit kein Unsinn auf den AVR losgelassen wird. Mit der Direktive .EXIT kann man
das erreichen:

.EQU taktfrequenz=4000000
.EQU teiler=64
.EXIT (taktfrequenz/teiler)>65535

Damit ist z.B. sichergestellt, dass auch bei anderen Taktfrequenzen kein 16-Bit-Zählerüberlauf zu befürchten ist,
ohne dass es der Assemblerprogrammierer merkt.

An den Seitenanfang

Verwendung von Makros


Makros werden vom Assembler gespeichert und erst beim Aufruf ihres Namens in den Code eingefügt, z.B. so

.MACRO mtest
.nop
.ENDM
;
; Hier wird das Makro eingefügt
;
mtest

Der Code im Makro ist mittels übergebenen Parametern variierbar. Die Parameter heißen @0 bis @9. Z.B. so

;
; Register global definieren
;
.DEF rmp,R16
.MACRO mtest
ldi @0,@1 ; Erwartet Register als ersten Param, Konstante als
zweiten
clr @0
.ENDM
;
; Makro einfügen
;
mtest rmp,50

Die Verwendung von Makros weist bei diesem Assembler die Besonderheit auf, dass alle im Makro definierten
Marken nur innerhalb des entsprechenden Makros gültig sind. Das verhindert, dass bei mehrfacher Verwendung
des Makros Konfusion auftritt. Global definierte Symbole sind von innerhalb des Makros zugänglich, daher darf
auch bei allen Makro-internen Symbolen kein Namenskonflikt auftreten. Wegen der lokalen Definition von
Marken innerhalb des Makros ist es normalerweise nicht möglich, interne Marken außerhalb des Makros zu
verwenden. Um dennoch eine Exportmöglichkeit zu haben, kann man mit der Direktive
.SETGLOBAL Marke1[, Marke2, ...]
den Wert nach außerhalb des Makros exportieren. Die so gebildete Variable wird zu Beginn jedes Aufrufs des
Makros jeweils auf den aktuellen Wert gesetzt.

Mit diesem Instrumentarium ist die Möglichkeit gegeben, umfangreiche Bibliotheken für immer wiederkehrende
Aufgaben zu schreiben. Weil der Code nur dann eingefügt wird, wenn das Makro auch tatsächlich im Code
aufgerufen wird, wird kein Platz verschwendet.

An den Seitenanfang

Verwendung von besonderen literalen Konstanten


gavrasm ermölicht die Verwendung von ASCII-Kontrollzeichen in Zeichenkonstanten, also z.B.

.DB "Dies ist die erste Zeile.\m\jDies ist die zweite Zeile."

Ein '\'-Zeichen wird mit zwei '\' eingefügt. Im Gegensatz zu anderen Assemblern werden ';' in Zeichenketten
richtig erkannt und behandelt.

An den Seitenanfang

Trennzeichen in Binär- und Hex-Konstanten


Der Assembler erlaubt die Verwendung des Punktes als Trennzeichen in Konstanten, wie z.B.

.EQU abc = 0b0001.0010


.EQU def = 0x0FFF.FFFF

Versuchen Sie diesen Quellcode niemals mit einem anderen Assembler zu assemblieren!

An den Seitenanfang

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gavrasm/gavrasmi.html1/20/2009 7:30:35 PM
http://www.avr-asm-tutorial.net/gavrasm/gavrasmw/LiesMich.txt

Programm GAVRASMW
-----------------

Gerd's kleiner Helfer zum Assemblieren von AVR Quellcode mit dem
Kommandozeilen-Assembler GAVRASM in einer fensterorientierten
Umgebung.

Freeware fr Windows, letzte Aenderung Oktober 2004


Freier Download unter
http://www.avr-asm-tutorial.net/gavrasm/GAVRASMI.html#caller

Features:
- Erzeugt bequeme Batchdateien zum Aufruf des Assemblers.
- Einmal konfiguriert werden alle notwendigen Informationen
in einer Projektdatei gespeichert, und zum Assemblieren ist
nur ein Mausklick noetig.
- Die Aufrufparameter beim Assemblieren sind bequem einstellbar.
- Die Listdatei und die erzeugte Batchdatei lassen sich bequem
betrachten.
- Editieren der Quelldatei sowie aller Include-Dateien mit Anzeige
der Zeilen- und Spalteninformationen zum einfachen Entwanzen.
- Wenn die Listdatei betrachtet wird und dort auf Fehler
hingewiesen wird, laeszst sich direkt die zugehoerige Quelldatei
oeffnen und die fehlerhafte Zeile kann editiert werden.

Installation:
- Entpacken des Zip-Archivs in einen Ordner, in dem Sie
Schreibrechte haben.
- Erstellen Sie eine Referenz auf die ausfuehrbare Datei auf der
Arbeitsoberflaeche oder im Startmenu.

Ein neues Projekt erzeugen:


- gavrasmw starten.
- "Setup" aus dem Menue waehlen.
Im Fensterbereich "gavrasm" waehlen Sie "Select" und navigieren
sie zu der ausfuehrbaren Datei "gavrasm.exe".
Im Fensterbereich "Parameter" waehlen Sie die gewuenschten
Parameter fuer den Assembler-Aufruf aus.
Im Fensterbereich "Source Code File" waehlen sie "Select" und
navigieren Sie zu der gewuenschten Quellcodedatei (dabei koennen
Sie auch neue Ordner und eine neue Hauptdatei erzeugen).
Entweder mit "Save as default" (gavrasmw startet dann immer mit
diesen Einstellungen) oder "Save as Project file" schlieszen.
Wenn die Projektdatei als neues Projekt gespeichert werden
soll, vergeben Sie einen neuen Dateinamen.
Mit dem Knopf "Close" das Fenster schlieszen.
- "Edit" und "Source" aus dem Menue waehlen. Ist die Haupt-
Quelldatei noch nicht vorhanden, dann oeffnet sich der Editor mit
mit einem Standardinhalt. Editieren Sie die Quelldatei und
schlieszen den Editor mit "File" und "Save".
- Wenn Sie eine Zeile mit einer Include-Direktive im Quellcode
haben und diese Include-Datei keine Standard "*def.inc"-Datei
ist, dann koennen Sie mit im Menue mit "Edit" und dem
entsprechenden Menue-Eintrag diese Include-Datei editieren.
Wenn die Include-Datei noch nicht existiert, dann oeffnet
sich diese mit einem standardisierten Header-Eintrag.
Zur Zeit koennen maximal fuenf Include-Dateien verwaltet
werden. Die Include-Dateien koennen beliebig tief
verschachtelt sein.
- Waehle "Assemble" im Hauptfenster um den Assembler in
einer Kommandozeile zu starten. Dies erzeugt die
Batchdatei und startet diese.
- Um die List-Ausgabe oder die Error-Ausgabe des Assemblers
zu betrachten, waehlen Sie "View" und "Listfile" resp. "View"
und "Errorfile". Falls hierin Fehler berichtet werden,
verwenden Sie "Error" und "FindNext", um zu den fehlerhaften
Zeilen zu navigieren. Befinden Sie sich bei einer Zeile
mit einer Fehlermeldung, waehlen Sie "Error" und "Open file"
um die Quelldatei in einem separaten Editorfenster zu oeffnen.
Korrigieren Sie den Fehler, speichern Sie die Datei und
schlieszen Sie das Fenster. Navigieren Sie dann zum naechsten
Fehler, falls noch welche enthalten sind.
- Betrachten Sie die Batchdatei mit "View" und
"Batchfile". Aenderungen in dieser Datei mit einem
externen Editor werden bei der naechsten "Assemble"-
Operation ueberschrieben!

Ein bestehendes Projekt oeffnen:


- Starte gavrasmw.
- Waehle im Menue "Setup". Wenn Sie mit einem anderen
als dem Standardprojekt arbeiten wollen, waehlen Sie
"Load Project File" und navigieren Sie zu der
gewuenschten Projektdatei (Endung: *.asw").

Berichte ueber Bugs in dieser Software an


info@avr-asm-tutorial.net
mit dem Betreff "gavrasm-caller, Oktober version".

http://www.avr-asm-tutorial.net/gavrasm/gavrasmw/LiesMich.txt1/20/2009 7:30:37 PM
SRAM im AVR

Pfad: Home => AVR-Überblick => Programmiertechniken => SRAM-Verwendung

Programmiertechnik für Anfänger in AVR


Assemblersprache
Verwendung von SRAM in AVR Assembler
Alle AVR-Typen verfügen in gewissem Umfang über Statisches RAM (SRAM) an Bord. Bei sehr
einfachen Assemblerprogrammen kann man es sich im Allgemeinen leisten, auf die Verwendung dieser
Hardware zu verzichten und alles in Registern unterzubringen. Wenn es aber eng wird im
Registerbereich, dann sollte man die folgenden Kenntnisse haben, um einen Ausweg aus der
Speicherenge zu nehmen.

Was ist SRAM?

SRAM sind Speicherstellen, die im Gegensatz zu Registern nicht direkt in die Recheneinheit (Arithmetic
and Logical Unit ALU, manchmal aus historischen Gründen auch Akkumulator genannt) geladen und
verarbeitet werden können. Ihre Verwendung ist daher auf den Umweg über ein Register angewiesen. Im
dargestellten Beispiel wird ein Wert von der Adresse im SRAM in das Register R2 geholt (1.
Instruktion), irgendwie mit dem Inhalt von Register R3 verknüpft und das Ergebnis in Register R3
gespeichert (Instruktion 2). Im letzten Schritt kann der geänderte Wert auch wieder in das SRAM
geschrieben werden (3.Instruktion).

Es ist daher klar, dass SRAM-Daten langsamer zu verarbeiten sind als Daten in Registern. Dafür besitzt
schon der zweitkleinste AVR immerhin 128 Bytes an SRAM-Speicher. Da passt schon einiges mehr rein
als in 32 popelige Register.

Die größeren AVR ab AT90S8515 aufwärts bieten neben den eingebauten 512 Bytes zusätzlich die
Möglichkeit, noch externes SRAM anzuschließen. Die Ansteuerung in Assembler erfolgt dabei in
identischer Weise wie internes RAM. Allerdings belegt das externe SRAM eine Vielzahl von Portpins
für Adress- und Datenleitungen und hebt den Vorteil der internen Bus-Gestaltung bei den AVR wieder
auf.

Zum Seitenanfang

Wozu kann man SRAM verwenden?

SRAM bietet über das reine Speichern von Bytes an festen Speicherplätzen noch ein wenig mehr. Der
Zugriff kann nicht nur mit festen Adressen, sondern auch mit Zeigervariablen erfolgen, so dass eine
fließende Adressierung der Zellen möglich ist. So können z.B. Ringpuffer zur Zwischenspeicherung
oder berechnete Tabellen verwendet werden. Das geht mit Registern nicht, weil die immer eine feste
Adresse benötigen.

Noch relativer ist die Speicherung über einen Offset. Dabei steht die Adresse in einem Pointerregister, es
wird aber noch ein konstanter Wert zu dieser Adresse addiert und dann erst gespeichert oder gelesen.
Damit lassen sich Tabellen noch raffinierter verwenden.

Die wichtigste Anwendung für SRAM ist aber der sogenannte Stack oder Stapel, auf dem man Werte
zeitweise ablegen kann, seien es Rücksprungadressen beim Aufruf von Unterprogrammen, bei der
Unterbrechung des Programmablaufes mittels Interrupt oder irgendwelche Zwischenwerte, die man
später wieder braucht und für die ein extra Register zu schade ist.

Zum Seitenanfang

Wie verwendet man SRAM?

Um einen Wert in eine Speicherstelle im SRAM abzulegen, muss man seine Adresse festlegen. Das
verwendbare SRAM reicht von Adresse 0x0060 bis zum jeweiligen Ende des SRAM-Speichers (beim
AT90S8515 ist das ohne externes SRAM z.B. 0x025F). Mit dem Befehl

STS 0x0060, R1

wird der Inhalt des Registers R1 in die Speicherzelle im SRAM kopiert. Mit

LDS R1, 0x0060

wird vom SRAM in das Register kopiert. Das ist der direkte Weg mit einer festen Adresse, die vom
Programmierer festgelegt wird.

Um das Hantieren mit festen Adressen und deren möglicherweisen späteren Veränderung bei
fortgeschrittener Programmierkunst sowie das Merken der Adresse zu erleichtern empfiehlt der
erfahrene Programmierer wieder die Namensvergabe, wie im folgenden Beispiel:

.EQU MeineLieblingsSpeicherzelle = 0x0060


STS MeineLieblingsSpeicherzelle, R1

Aber auch das ist noch nicht allgemein genug. Mit

.EQU MeineLieblingsSpeicherzelle = SRAM_START


.EQU MeineZweiteLieblingsSpeicherzelle = SRAM_START

ist die in der Include-Datei eingetragene Adresse der SRAM-Speicherzellen noch allgemeingültiger
angegeben.

Zugegeben, kürzer ist das alles nicht, aber viel leichter zu merken.

Organisation als Datensegment

Bei etwas komplexeren Datenstrukturen empfiehlt sich das Anlegen in einem Datensegment. Eine solche
Struktur sieht dann z. B. so aus:

.DSEG ; das ist der Beginn des Datensegments, die folgenden Einträge organisieren SRAM
.ORG SRAM_START ; an den Beginn des SRAM legen.
;
EinByte: ; ein Label als Symbol für die Adresse einer Speicherzelle
.BYTE 1 ; ein Byte dafuer reservieren
;
ZweiBytes: ; ein Label als Symbol für die Adresse zweier aufeinander folgender Speicherzellen
.BYTE 2 ; zwei Bytes reservieren
;
.EQU Pufferlaenge = 32 ; definiert die Laenge eines Datenpuffers
Buffer_Start: ; ein Label fuer den Anfang des Datenpuffers
.BYTE Pufferlaenge ; die folgenden 32 Speicherzellen als Datenpuffer reservieren
Buffer_End: ; ein Label fuer das Ende des Datenpuffers
;
.CSEG ; Ende des Datensegments, Beginn des Programmsegments

Das Datensegment enthält also ausschließlich Labels, über die die entsprechenden reservierten
Speicherzellen später adressiert werden können, und .BYTE-Direktiven, die die Anzahl der zu
reservierenden Zellen angeben. Ziel der ganzen Angelegenheit ist das Anlegen einer flexibel änderbaren
Struktur für den Zugriff über Adresssymbole. Inhalte für diese Speicherzellen werden dabei nicht
erzeugt, es gibt auch keine Möglichkeit, den Inhalt von SRAM-Speicherzellen beim Brennen des Chips
zu manipulieren.

Zugriffe auf das SRAM über Pointer

Eine weitere Adressierungsart für SRAM-Zugriffe ist die Verwendung von Pointern, auch Zeiger
genannt. Dazu braucht es zwei Register, die die Adresse enthalten. Wie bereits in der Pointer-Register-
Abteilung erläutert sind das die Registerpaare X mit XL/XH (R26, R27), Y mit YL/YH (R28, R29) und
Z mit ZL und ZH (R30, R31). Sie erlauben den Zugriff auf die jeweils addressierte Speicherzelle direkt
(z.B. ST X, R1), nach vorherigem Vermindern der Adresse um Eins (z.B. ST -X,R1) oder mit
anschliessendem Erhöhen um Eins (z.B. ST X+, R1). Ein vollständiger Zugriff auf drei Zellen sieht also
etwa so aus:

.EQU MeineLieblingsZelle = 0x0060


.DEF MeinLieblingsRegister = R1
.DEF NochEinRegister = R2
.DEF UndNochEinRegister = R3
LDI XH, HIGH(MeineLieblingszelle)
LDI XL, LOW(MeineLieblingszelle)
LD MeinLieblingsregister, X+
LD NochEinRegister, X+
LD UndNochEinRegister, X

Sehr einfach zu bedienen, diese Pointer. Und nach meinem Dafürhalten genauso einfach (oder schwer)
zu verstehen wie die Konstruktion mit dem Dach in gewissen Hochsprachen.

Indizierte Zugriffe über Pointer

Die dritte Konstruktion ist etwas exotischer und nur erfahrene Programmierer greifen in ihrer
unermesslichen Not danach. Nehmen wir mal an, wir müssen sehr oft und an verschiedenen Stellen eines
Programmes auf die drei Positionen im SRAM zugreifen, weil dort irgendwelche wertvollen
Informationen stehen. Nehmen wir ferner an, wir hätten gerade eines der Pointerregister so frei, dass wir
es dauerhaft für diesen Zweck opfern könnten. Dann bleibt bei dem Zugriff nach ST/LD-Muster immer
noch das Problem, dass wir das Pointerregister immer anpassen und nach dem Zugriff wieder in einen
definierten Zustand versetzen müssten. Das ist eklig. Zur Vermeidung (und zur Verwirrung von
Anfängern) hat man sich den Zugriff mit Offset einfallen lassen (deutsch etwa: Ablage). Bei diesem
Zugriff wird das eigentliche Zeiger-Register nicht verändert, der Zugriff erfolgt mit temporärer Addition
eines festen Wertes. Im obigen Beispiel würde also folgende Konstruktion beim Zugriff auf die
Speicherzelle 0x0062 erfolgen. Zuerst wäre irgendwann das Pointer-Register zu setzen:

.EQU MeineLieblingsZelle = 0x0060


.DEF MeinLieblingsRegister = R1
LDI YH, HIGH(MeineLieblingszelle)
LDI YL, LOW(MeineLieblingszelle)

Irgendwo später im Programm will ich dann auf Zelle 0x0062 zugreifen:

STD Y+2, MeinLieblingsRegister

Obacht! Die zwei werden nur für den Zugriff addiert, der Registerinhalt von Y wird nicht verändert. Zur
weiteren Verwirrung des Publikums geht diese Konstruktion nur mit dem Y- und dem Z-Pointer, nicht
aber mit dem X-Pointer!

Der korrespondierende Befehl für das indizierte Lesen eines SRAM-Bytes

LDD MeinLieblingsRegister, Y+2

ist ebenfalls vorhanden.

Das war es schon mit dem SRAM, wenn da nicht der Stack noch wäre.

Zum Seitenanfang

Verwendung von SRAM als Stack

Die häufigste und bequemste Art der Nutzung des SRAM ist der Stapel, englisch stack genannt. Der
Stapel ist ein Türmchen aus Holzklötzen. Jedes neu aufgelegte Klötzchen kommt auf den schon
vorhandenen Stapel obenauf, jede Entnahme vom Turm kann immer nur auf das jeweils oberste
Klötzchen zugreifen, weil sonst der ganze schöne Stapel hin wäre. Das kluge Wort für diese Struktur ist
Last-In-First-Out (LIFO) oder schlichter: die Letzten werden die Ersten sein.

Zur Verwirrung des Publikums wächst der Stapel bei fast allen Mikroprozessoren aber nicht von der
niedrigsten zu höheren Adressen hin, sondern genau umgekehrt. Wir könnten sonst am Anfang des
SRAMs unsere schönen Datenstrukturen nicht anlegen.

Einrichten des Stapels

Um vorhandenes SRAM für die Anwendung als Stapel herzurichten ist zu allererst der Stapelzeiger
einzurichten. Der Stapelzeiger ist ein 16-Bit-Zeiger, der als Port ansprechbar ist. Das Doppelregister
heißt SPH:SPL. SPH nimmt das obere Byte der Adresse, SPL das niederwertige Byte auf. Das gilt aber
nur dann, wenn der Chip über mehr als 256 Byte SRAM verfügt. Andernfalls fehlt SPH und kann/muss
nicht verwendet werden. Wir tun im nächsten Beispiel so, als ob wir mehr als 256 Bytes SRAM haben.

Zum Einrichten des Stapels wird der Stapelzeiger mit der höchsten verfügbaren SRAM-Adresse
bestückt. (Der Stapel oder Turm wächst nach unten, d.h. zu niedrigeren Adressen hin.)

.DEF MeinLieblingsRegister = R16


LDI MeinLieblingsRegister, HIGH(RAMEND) ; Oberes Byte
OUT SPH,MeinLieblingsRegister ; an Stapelzeiger
LDI MeinLieblingsRegister, LOW(RAMEND) ; Unteres Byte
OUT SPL,MeinLieblingsRegister ; an Stapelzeiger

Die Größe RAMEND ist natürlich prozessorspezifisch und steht in der Include-Datei für den Prozessor.
So steht z.B. in der Datei 8515def.inc die Zeile

.equ RAMEND =$25F ;Last On-Chip SRAM Location

Die Datei 8515def.inc kommt mit der Assembler-Direktive

.INCLUDE "C:\irgendwo\8515def.inc"

irgendwo am Anfang des Assemblerprogrammes hinzu.

Damit ist der Stapelzeiger eingerichtet und wir brauchen uns im weiteren nicht mehr weiter um diesen
Zeiger kümmern, weil er ziemlich automatisch manipuliert wird.

Verwendung des Stapels

Die Verwendung des Stapels ist unproblematisch. So lassen sich Werte von Registern auf den Stapel
legen:

PUSH MeinLieblingsregister ; Ablegen des Wertes

Wo der Registerinhalt abgelegt wird, interessiert uns nicht weiter. Dass dabei der Zeiger automatisch
erniedrigt wird, interessiert uns auch nicht weiter. Wenn wir den abgelegten Wert wieder brauchen, geht
das einfach mit:

POP MeinLieblingsregister ; Rücklesen des Wertes

Mit POP kriegen wir natürlich immer nur den Wert, der als letztes mit PUSH auf den Stapel abgelegt
wurde. Wichtig: Selbst wenn der Wert vielleicht gar nicht mehr benötigt wird, muss er mit Pop wieder
vom Stapel! Das Ablegen des Registers auf den Stapel lohnt also programmtechnisch immer nur dann,
wenn

● der Wert in Kürze, d.h. ein paar Befehle weiter im Ablauf, wieder gebraucht wird,
● alle Register in Benutzung sind und,
● keine Möglichkeit zur Zwischenspeicherung woanders besteht.

Wenn diese Bedingungen nicht vorliegen, dann ist die Verwendung des Stapels ziemlich nutzlos und
verschwendet bloss Zeit.

Stapel zum Ablegen von Rücksprungadressen

Noch wertvoller ist der Stapel bei Sprüngen in Unterprogramme, nach deren Abarbeitung wieder exakt
an die aufrufende Stelle im Programm zurück gesprungen werden soll. Dann wird beim Aufruf des
Unterprogrammes die Rücksprungadresse auf den Stapel abgelegt, nach Beendigung wieder vom Stapel
geholt und in den Programmzähler bugsiert. Dazu dient die Konstruktion mit dem Befehl

RCALL irgendwas ; Springe in das UP irgendwas


[...] hier geht es normal weiter im Programm

Hier landet der Sprung zum Label irgendwas irgendwo im Programm,

irgendwas: ; das hier ist das Sprungziel


[...] Hier wird zwischendurch irgendwas getan
[...] und jetzt kommt der Rücksprung an den Aufrufort im Programm:
RET

Beim RCALL wird der Programmzähler, eine 16-Bit-Adresse, auf dem Stapel abgelegt. Das sind zwei
PUSHs, dann sind die 16 Bits auf dem Stapel. Beim Erreichen des Befehls RET wird der
Programmzähler mit zwei POPs wieder hergestellt und die Ausführung des Programmes geht an der
Stelle weiter, die auf den RCALL folgt.
Damit braucht man sich weiter um die Adresse keine Sorgen zu machen, an der der Programmzähler
abgelegt wurde, weil der Stapel automatisch manipuliert wird. Selbst das vielfache Verschachteln
solcher Aufrufe ist möglich, weil jedes Unterprogramm, das von einem Unterprogramm aufgerufen
wurde, zuoberst auf dem Stapel die richtige Rücksprungadresse findet.

Unverzichtbar ist der Stapel bei der Verwendung von Interrupts. Das sind Unterbrechungen des
Programmes aufgrund von äußeren Ereignissen, z.B. Signale von der Hardware. Damit nach Bearbeitung
dieser äußeren "Störung" der Programmablauf wieder an der Stelle vor der Unterbrechung fortgesetzt
werden kann, muss die Rücksprungadresse bei der Unterbrechung auf den Stapel. Interrupts ohne Stapel
sind also schlicht nicht möglich.

Fehlermöglichkeiten beim (Hoch-)Stapeln

Für den Anfang gibt es reichlich Möglichkeiten, mit dem Stapeln üble Bugs zu produzieren.

Sehr beliebt ist die Verwendung des Stapels ohne vorheriges Setzen des Stapelzeigers. Da der Zeiger zu
Beginn bei Null steht, klappt aber auch rein gar nix, wenn man den ersten Schritt vergisst.

Beliebt ist auch, irgendwelche Werte auf dem Stapel liegen zu lassen, weil die Anzahl der POPs nicht
exakt der Anzahl der PUSHs entspricht. Das ist aber schon seltener. Es kommt vorzugsweise dann vor,
wenn zwischendurch ein bedingter Sprung nach woanders vollführt wurde und dort beim Programmieren
vergessen wird, dass der Stapel noch was in Petto hat.

Noch seltener ist ein Überlaufen des Stapels, wenn zuviele Werte abgelegt werden und der Stapelzeiger
sich bedrohlich auf andere, am Anfang des SRAM abgelegten Werte zubewegt oder noch niedriger wird
und in den Bereich der Ports und der Register gerät. Das hat ein lustiges Verhalten des Chips, auch
äußerlich, zur Folge. Kommt aber meistens fast nie vor, nur bei vollstopftem SRAM.

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/sram.html1/20/2009 7:31:18 PM
Ports im AVR

Pfad: Home => AVR-Überblick => Programmiertechniken => Ports

Programmiertechnik für Anfänger in AVR Assemblersprache


Was ist ein Port?
Ports sind eigentlich ein Sammelsurium verschiedener Speicher. In der Regel dienen sie der Kommunikation mit irgendeiner internen Gerätschaft wie z.B. den Timern oder der Seriellen Schnittstelle oder der
Bedienung von äußeren Anschlüssen wie den Parallel-Schnittstellen des AVR. Der wichtigste Port wird weiter unten besprochen: das Status-Register, das an das wichtigste interne Gerät, nämlich den
Akkumulator, angeschlossen ist.

Port-Organisation

Es gibt insgesamt 64 direkt adressierbare Ports, die aber nicht bei allen AVR-Typen auch tatsächlich physikalisch vorhanden sind. Bei größeren ATmega gibt es neben den direkt adressierbaren Ports noch
indirekt adressierbare Ports, doch dazu später mehr.

Je nach Größe und Ausstattung des Typs sind eine Reihe von Ports sinnvoll ansprechbar. Welche der Ports in welchem Typ tatsächlich vorhanden sind, ist letztlich aus den Datenblättern zu erfahren. Hier ein
Ausschnitt aus den Ports des ATmega8 (von ATMEL zur allgemeinen Verwirrung auch "Register" genannt:

Ports haben eine feste Adresse (in dem oben gezeigten Ausschnitt z. B. 0x3F für den Port SREG, 0x steht dabei für hexadezimal!), über die sie angesprochen werden können. Die Adresse gilt teilweise
unabhängig vom AVR-Typ, teilweise aber auch nicht. So befindet sich das Statusregister SREG immer an der Adresse 0x3F, der Ausgabeport der Parallelschnittstelle B immer an der Portadresse 0x18. Ports
nehmen oft ganze Zahlen auf, sie können aber auch aus einer Reihe einzelner Steuerbits bestehen. Diese einzelnen Bits haben dann eigene Namen, so dass sie mit Befehlen zur Bitmanipulation angesteuert
werden können. In der Portliste hat auch jedes Bit in dem jeweiligen Port seinen speziellen symbolischen Namen, z. B. hat das Bit 7 im Port "GICR" den symbolischen Namen "INT1".

Port-Symbole, Include

Diese Adressen und Bit-Nummern muss man sich aber nicht merken. In den Include-Dateien zu den einzelnen AVR-Typen, die der Hersteller zur Verfügung stellt, sind die jeweiligen verfügbaren Ports und ihre
Bits mit wohlklingenden Namen belegt. So ist in den Include-Dateien die Assemblerdirektive

.EQU PORTB, 0x18

angegeben und wir müssen uns fürderhin nur noch merken, dass der Port B PORTB heißt. Fü das Bit INT1 im Port GICR ist in der Include-Datei definiert:

.EQU INT1, 7

Die Include-Datei des AVR ATmega8515 heißt "m8515def.inc" und kommt mit folgender Direktive in die Quellcode-Datei:

.INCLUDE "m8515def.inc"
oder, wenn man nicht mit dem Studio arbeitet,
.INCLUDE "C:\PfadNachIrgendwo\m8515def.inc

und alle für diesen Typ bekannten Portregister und Steuerbits sind jetzt mit ihren symbolischen Alias-Namen leichter ansprechbar.

Ports setzen

In Ports kann und muss man Werte schreiben, um die betreffende Hardware zur Mitarbeit zu bewegen. So enthält z.B. das MCU General Control Register, genannt MCUCR, eine Reihe von Steuerbits, die das
generelle Verhalten des Chips beeinflussen (siehe im Ausschnitt oben bzw. die Beschreibung des MCUCR im Detail). MCUCR ist ein mit Einzelbits vollgepackter Port, in dem jedes Bit noch mal einen eigenen
Namen hat (ISC00, ISC01, ...). Wer den Port benötigt, um den AVR in den Tiefschlaf zu versetzen, muss sich im Typenblatt die Wirkung dieser Sleep-Bits heraussuchen und durch eine Folge von Instruktionen
die entsprechende einschläfernde Wirkung programmieren, für den ATmega8 also z.B. so: ...

.DEF MeinLieblingsregister = R16


LDI MeinLieblingsregister, 0b10000000
OUT MCUCR, MeinLieblingsregister
SLEEP

Der Out-Befehl bringt den Inhalt meines Lieblingsregisters, nämlich ein gesetztes Sleep-Enable-Bit SE, zum Port MCUCR und versetzt den AVR gleich und sofort in den Schlaf, wenn er im ausgeführten Code
auf eine SLEEP-Instruktion trifft. Da gleichzeitig alle anderen Bits mitgesetzt werden und mit Sleep-Mode SM=0 als Modus der Halbschlaf eingestellt wurde, geht der Chip nicht völlig auf Tauchstation. In
diesem Zustand wird die Befehlsausführung eingestellt, die Timer und andere Quellen von Interrupts bleiben aber aktiv und können den Halbschlaf jederzeit unterbrechen, wenn sich was Wichtiges tut.

Ports transparenter setzen

Weil "LDI MeinLieblingsregister, 0b10000000" eine ziemlich intransparente Angelegenheit ist, weil zum Verständnis dafür, was eigentlich hier gemacht wird, ein Blick in die Portbits im Datenblatt nötig ist,
schreibt man dies besser so:

LDI MeinLieblingsRegister, 1<<SE

"1<<SE" nimmt eine binäre Eins (= 0b00000001) und schiebt diese SE mal links (<<). SE ist im Falle des ATmega8 als 7 definiert, also die 1 sieben mal links schieben. Das Ergebnis (= 0b10000000) ist
gleichbedeutend mit dem oben eingefügten Bitmuster und setzt das Bit SE im Port MCUCR auf Eins. Wenn wir gleichzeitig auch noch das Bit SM0 auf 1 setzen wollen (was einen der acht möglichen
Tiefschlafmodi einschaltet, dann wird das so formuliert:

LDI MeinLieblingsRegister, (1<<SE) | (1<<SM0)

Der vertikale Strich zwischen beiden Teilergebnissen ist ein binäres ODER, d. h. dass alle auf Eins gesetzten Bits in einem der beiden Teilausdrücke in Klammern Eins werden, also sowohl das Bit SE (= 7) als
auch das Bit SM0 (= 4) gesetzt sind, woraus sich 0b10010000 ergibt.

Noch mal zum Merken: die Linksschieberei wird nicht im Prozessor vollzogen, nur beim Assemblieren. Die Instruktion LDI wird auch nicht anders übersetzt, wenn wir die Schieberei verwenden, und ist auch
im Prozessor nur eine einzige Instruktion. Von den Symbolen SE und SM0 hat der Prozessor selbst sowieso keine Ahnung, das ist alles nur für den Quellcode-Schreiber von Bedeutung.

Die Linksschieberei hat den immensen Vorteil, dass nun für jeden aufgeklärten Menschen sofort erkennbar ist, dass hier die Bits SE und SM0 manipuliert werden. Nicht dass jeder sofort wüsste, dass damit der
Schlafmodus eingestellt wird, aber es liegt wenigstens in der Assoziation näher als 0b10010000.

Noch ein Vorteil: das SE-Bit liegt bei anderen Prozessoren woanders im Port MCUCR als in Bit 7, z. B. im AT90S8515 lag es in Bit 5. SM0 ist bei diesem Typ gar nicht bekannt, bei einer Portierung unseres
Quellcodes für den ATmega8 auf diesen Typ kriegen wir dann eine Fehlermeldung (SM0 ist dort nicht definiert) und wir wissen dann sofort, wo wir suchen und nacharbeiten müssen.

Ports lesen

Umgekehrt lassen sich die Portinhalte mit dem IN-Befehl in beliebige Register einlesen und dort weiterverarbeiten. So lädt

.DEF MeinLieblingsregister = R16


IN MeinLieblingsregister, MCUCR

den lesbaren Teil des Ports MCUCR in das Register R16. Den lesbaren Teil deswegen, weil es bei vielen Ports auch nicht belegte Bits gibt, die dann immer als Null eingelesen werden.

Oft will man nur bestimmte Portbits setzen und die Porteinstellung ansonsten so lassen. Das geht mit Lesen-Ändern-Schreiben (Read-Modify-Write) z. B. so:

IN MeinLieblingsregister, MCUCR
SBR MeinLieblingsRegister, (1<<SE) | (1<<SM0)
OUT MCUCR,MeinLieblingsRegister

Braucht aber halt drei Instruktionen.

Auf Portbits reagieren

Noch öfter als ganze Ports einlesen muss man auf Änderungen bestimmter Bits der Ports prüfen. Dazu muss nicht der ganze Port gelesen und verarbeitet werden. Es gibt hierfür spezielle Sprungbefehle, die aber
im Kapitel Springen vorgestellt werden. Umgekehrt kommt es oft vor, dass ein bestimmtes Portbit gesetzt oder rückgesetzt werden muss. Auch dazu braucht man nicht den ganzen Port lesen und nach der
Änderung im Register dann den neuen Wert wieder zurückschreiben. Die beiden Befehle heissen SBI (Set Bit I/O-Register) und CBI (Clear Bit I/O-Register). Ihre Anwendung geht z.B. so:

.EQU Aktivbit=0 ; Das zu manipulierende Bit des Ports


SBI PortB, Aktivbit ; Das Bit wird Eins
CBI PortB, Aktivbit ; Das Bit wird Null

Die beiden Instruktionen haben einen gravierenden Nachteil: sie lassen sich nur auf Ports bis zur Adresse 0x1F anwenden, für Ports darüber sind sie leider unzulässig. Für Ports oberhalb des mit IN und OUT
beschreibbaren Adressraums geht das natürlich schon gar nicht.

Porteinblendung im Speicherraum

Für den Zugang zu den Ports, die im nicht direkt zugänglichen Adressraum liegen (z. B. bei einigen großen ATmega und ATxmega) und für den Exotenprogrammierer gibt es wie bei den Registern auch hier die
Möglichkeit, die Ports wie ein SRAM zu lesen und zu schreiben, also mit dem LD- bzw. der ST-Instruktion. Da die ersten 32 Adressen im SRAM-Speicherraum schon mit den Registern belegt sind, werden die
Ports mit ihrer um 32 erhöhten Adresse angesprochen, wie z.B. bei

.DEF MeinLieblingsregister = R16


LDI ZH,HIGH(PORTB+32)
LDI ZL,LOW(PORTB+32)
LD MeinLieblingsregister,Z

Das macht nur im Ausnahmefall einen Sinn, geht aber halt auch. Es ist der Grund dafür, warum das SRAM erst ab Adresse 0x60 beginnt (0x20 für die Register, 0x40 für die Ports reserviert), bei großen ATmega
erst bei 0x100.

Zum Seitenanfang

Details wichtiger Ports in den AVR


Die folgende Tabelle kann als Nachschlagewerk für die wichtigsten gebräuchlichsten Ports im AT90S8515 dienen. Sie enthält nicht alle möglichen Ports. Insbesondere die Ports der MEGA-Typen und der
AT90S4434/8535 sind der Übersichtlichkeit halber nicht darin enthalten! Bei Zweifeln immer die Originaldokumentation befragen!
Gerät Link Register Link
Akkumulator SREG Status Register SREG
Stack SPL/SPH Stackpointer SPL/SPH
Ext.SRAM/
MCUCR MCU General Control Register MCUCR
Ext.Interrupt
Interrupt Mask Register GIMSK
Ext.Int. INT
Flag Register GIFR
Timer Int Mask Register TIMSK
Timer Interrupts Timer Int.
Timer Interrupt Flag Register TIFR
Timer/Counter 0 Control Register TCCR0
Timer 0 Timer 0
Timer/Counter 0 TCNT0
Timer/Counter Control Register 1 A TCCR1A
Timer/Counter Control Register 1 B TCCR1B
Timer/Counter 1 TCNT1
Timer 1 Timer 1
Output Compare Register 1 A OCR1A
Output Compare Register 1 B OCR1B
Input Capture Register ICR1L/H
Watchdog Timer WDT Watchdog Timer Control Register WDTCR
EEPROM Adress Register EEAR
EEPROM EEPROM EEPROM Data Register EEDR
EEPROM Control Register EECR
Serial Peripheral Control Register SPCR
SPI SPI Serial Peripheral Status Register SPSR
Serial Peripheral Data Register SPDR
UART Data Register UDR
UART Status Register USR
UART UART
UART Control Register UCR
UART Baud Rate Register UBRR
Analog Comparator ANALOG Analog Comparator Control and Status Register ACSR
I/O-Ports IO-Ports

Zum Seitenanfang

Das Statusregister als wichtigster Port


Der am häufigste verwendete Port für den Assemblerprogrammierer ist das Statusregister mit den darin enthaltenen acht Bits. In der Regel wird auf diese Bits vom Programm aus nur lesend/auswertend
zugegriffen, selten werden Bits explizit gesetzt (mit dem Assembler-Befehl SEx) oder zurückgesetzt (mit dem Befehl CLx). Die meisten Statusbits werden von Bit-Test, Vergleichs- und Rechenoperationen
gesetzt oder rückgesetzt und anschliessend für Entscheidungen und Verzweigungen im Programm verwendet.

Die folgende Tabelle enthält eine Liste der Assembler-Instruktionen, die die jeweiligen Status-Bits beeinflussen.
Bit Rechnen Logik Vergleich Bits Schieben Sonstige
ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, AND, ANDI, OR, ORI, EOR, COM, NEG,
Z CP, CPC, CPI BCLR Z, BSET Z, CLZ, SEZ, TST ASR, LSL, LSR, ROL, ROR CLR
SBIW SBR, CBR
C ADD, ADC, ADIW, SUB, SUBI, SBC, SBCI, SBIW COM, NEG CP, CPC, CPI BCLR C, BSET C, CLC, SEC ASR, LSL, LSR, ROL, ROR -
ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, AND, ANDI, OR, ORI, EOR, COM, NEG,
N CP, CPC, CPI BCLR N, BSET N, CLN, SEN, TST ASR, LSL, LSR, ROL, ROR CLR
SBIW SBR, CBR
ADD, ADC, ADIW, DEC, INC, SUB, SUBI, SBC, SBCI, AND, ANDI, OR, ORI, EOR, COM, NEG,
V CP, CPC, CPI BCLR V, BSET V, CLV, SEV, TST ASR, LSL, LSR, ROL, ROR CLR
SBIW SBR, CBR
S SBIW - - BCLR S, BSET S, CLS, SES - -
H ADD, ADC, SUB, SUBI, SBC, SBCI NEG CP, CPC, CPI BCLR H, BSET H, CLH, SEH - -
T - - - BCLR T, BSET T, BST, CLT, SET - -
I - - - BCLR I, BSET I, CLI, SEI - RETI

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/ports.html1/20/2009 7:31:29 PM
Details wichtiger Ports im AVR

Pfad: Home => AVR-Überblick => Programmiertechniken => Ports => Details

Programmiertechnik für Anfänger in AVR


Assemblersprache
Die Tabelle der wichtigsten Ports in den ATMELAVR-Typen AT90S2313, 2323 und 8515.
Byteweise ansprechbare Ports oder Doppelregister sind nicht im Detail dargestellt. Keine Gewähr für
Richtigkeit der Angaben!

Status-Register, Akkumulatorflags

Port Funktion Port-Adresse RAM-Adresse


SREG Status Register Akkumulator 0x3F 0x5F

7 6 5 4 3 2 1 0
I T H S V N Z C

Bit Name Bedeutung Möglichkeiten Befehl


0: Interrupts ausgeschaltet CLI
7 I Globales Interrupt Flag
1: Interrupts erlaubt/eingeschaltet SEI
0: Gespeichertes Bit ist 0 CLT
6 T Bitspeicher
1: Gespeichertes Bit ist 1 SET
0: Kein Halbübertrag aufgetreten CLH
5 H Halbübertrags-Flag
1: Halbübertrag aufgetreten SEH
0: Vorzeichen positiv CLS
4 S Vorzeichen-Flag
1: Vorzeichen negativ SES
0: Kein Übertrag aufgetreten CLV
3 V Zweierkomplement-Übertrags-Flag
1: Übertrag aufgetreten SEV
0: Ergebnis war nicht negativ/kleiner CLN
2 N Negativ-Flag
1: Ergebnis war negativ/kleiner SEN
0: Ergebnis war nicht Null/ungleich CLZ
1 Z Null-Flag
1: Ergebnis war Null/gleich SEZ
0: Kein Übertrag aufgetreten CLC
0 C Übertrags-Flag
1: Übertrag aufgetreten SEC

Zum Seitenanfang

Stackpointer

Port Funktion Port-Adresse RAM-Adresse


SPL/SPH Stackpointer 003D/0x3E 0x5D/0x5E

Name Bedeutung Verfügbarkeit


SPL Low-Byte des Stackpointers Ab AT90S2313 aufwärts, nicht bei 1200
Ab AT90S8515 aufwärts, nur bei Devices mit >256 Byte
SPH High-Byte des Stackpointers
internem SRAM

Zum Seitenanfang

SRAM und External Interrupt Steuerung

Port Funktion Port-Adresse RAM-Adresse


MCUCR MCU General Control Register 0x35 0x55

7 6 5 4 3 2 1 0
SRE SRW SE SM ISC11 ISC10 ISC01 ISC00

Bit Name Bedeutung Möglichkeiten


0=Kein externes SRAM angeschlossen
7 SRE Ext.SRAM Enable
1=Externes SRAM ansprechen
0=Kein extra Wait Zyklus bei externem SRAM
6 SRW Ext.SRAM Wait States
1=Zusätzlicher Wait State bei externem SRAM
0=Ignoriere SLEEP Befehl
5 SE Sleep Enable
1=SLEEP-Befehle befolgen
0=Idle Mode (Halbschlaf)
4 SM Sleep Mode
1=Power Down Mode (Tiefschlaf)
00: Low-Pegel löst Interrupt aus
3 ISC11
Interruptsteuerung Pin INT1 01: Undefiniert
(Verknüpft mit GIMSK) 10: Fallende Flanke löst Interrupt aus
2 ISC10
11: Ansteigende Flanke löst Interrupt aus
00: Low-Pegel löst Interrupt aus
1 ISC01
Interruptsteuerung Pin INT0 01: Undefiniert
(Verknüpft mit GIMSK) 10: Fallende Flanke löst Interrupt aus
0 ISC00
11: Ansteigende Flanke löst Interrupt aus

Zum Seitenanfang

Externe Interrupt-Steuerung

Port Funktion Port-Adresse RAM-Adresse


GIMSK General Interrupt Maskenregister 0x3B 0x5B

7 6 5 4 3 2 1 0
INT1 INT0 - - - - - -

Bit Name Bedeutung Möglichkeiten


Interrupt durch externen Pin INT1 0: Externer INT1 ausgeschaltet
7 INT1
(Verknüpft mit Modus in MCUCR) 1: Externer INT1 eingeschaltet

Interrupt durch externen Pin INT0 0: Externer INT0 ausgeschaltet


6 INT0
(Verknüpft mit Modus in MCUCR) 1: Externer INT0 eingeschaltet
0...5 (Nicht benutzt)

Port Funktion Port-Adresse RAM-Adresse


GIFR General Interrupt Flag Register 0x3A 0x5A

7 6 5 4 3 2 1 0
INTF1 INTF0 - - - - - -

Bit Name Bedeutung Möglichkeiten


Interrupt durch externen Pin INT1
7 INTF1 Automatisch Rücksetzen durch Bearbeitung der
aufgetreten
Int-Routine oder
Interrupt durch externen Pin INT0 Rücksetzen per Befehl
6 INTF0
aufgetreten
0...5 (Nicht benutzt)

Zum Seitenanfang

Timer Interrupt-Steuerung

Port Funktion Port-Adresse RAM-Adresse


TIMSK Timer Interrupt Maskenregister 0x39 0x59

7 6 5 4 3 2 1 0
TOIE1 OCIE1A OCIE1B - TICIE1 - TOIE0 -

Bit Name Bedeutung Möglichkeiten


0: Kein Int bei Überlauf
7 TOIE1 Timer/Counter 1 Überlauf-Interrupt
1: Int bei Überlauf
0: Kein Int bei Erreichen Stand A
6 OCIE1A Timer/Counter 1 Vergleichszahl A Interrupt
1: Int bei Erreichen Stand in A
0: Kein Int bei Erreichen Stand B
5 OCIE1B Timer/Counter 1 Vergleichszahl B Interrupt
1: Int bei Erreichen Stand in B
4 (Nicht benutzt)
0: Kein Int bei Capture
3 TICIE1 Timer/Counter 1 Capture-Ereignis Interrupt
1: Int bei Capture
2 (Nicht benutzt)
0: Kein Int bei Überlauf
1 TOIE0 Timer/Counter 0 Überlauf-Interrupt
1: Int bei Überlauf
0 (Nicht benutzt)

Port Funktion Port-Adresse RAM-Adresse


TIFR Timer Interrupt Flag Register 0x38 0x58

7 6 5 4 3 2 1 0
TOV1 OCF1A OCF1B - ICF1 - TOV0 -

Bit Name Bedeutung Möglichkeiten


7 TOV1 Timer/Counter 1 Überlauf erreicht Interrupt-Modus:
6 OCF1A Timer/Counter 1 Vergleichszahl A erreicht Automatisches Rücksetzen
5 OCF1B Timer/Counter 1 Vergleichszahl B erreicht bei Bearbeitung der
zugehörigen Int-Routine
4 (Nicht benutzt)
3 ICF1 Timer/Counter 1 Capture-Ereignis eingetreten ODER
2 (Nicht benutzt) Polling-Modus:
1 TOV0 Timer/Counter 0 Überlauf aufgetreten Rücksetzen per
Befehl
0 (Nicht benutzt)

Zum Seitenanfang

Timer/Counter 0

Port Funktion Port-Adresse RAM-Adresse


TCCR0 Timer/Counter 0 Control Register 0x33 0x53

7 6 5 4 3 2 1 0
- - - - - CS02 CS01 CS00

Bit Name Bedeutung Möglichkeiten


000: Timer anhalten
001: Clock = Taktfrequenz
010: Clock = Taktfrequenz / 8
011: Clock = Taktfrequenz / 64
2..0 CS02..CS00 Timer Takt
100: Clock = Taktfrequenz / 256
101: Clock = Taktfrequenz / 1024
110: Clock = abfallende Flanke externer Pin T0
111: Clock = ansteigende Flanke externer Pin T0
3..7 (nicht benutzt)

Port Funktion Port-Adresse RAM-Adresse


TCNT0 Timer/Counter 0 Zählregister 0x32 0x52

Zum Seitenanfang

Timer/Counter 1

Port Funktion Port-Adresse RAM-Adresse


TCCR1A Timer/Counter 1 Control Register A 0x2F 0x4F

7 6 5 4 3 2 1 0
COM1A1 COM1A0 COM1B1 COM1B0 - - PWM11 PWM10

Bit Name Bedeutung Möglichkeiten


7 COM1A1
Compare Ausgang A 00: OC1A/B nicht verbunden
6 COM1A0 01: OC1A/B wechselt Polarität
5 COM1B1 10: OC1A/B auf Null setzen
Compare Ausgang A 11: OC1A/B auf Eins setzen
4 COM1B0
3
(nicht benutzt)
2
00: PWM aus
PWM11 01: 8-Bit PWM
1..0 Pulsweitengenerator
PWM10 10: 9-Bit PWM
11: 10-Bit PWM

Port Funktion Port-Adresse RAM-Adresse


TCCR1B Timer/Counter 1 Control Register B 0x2E 0x4E

7 6 5 4 3 2 1 0
ICNC1 ICES1 - - CTC1 CS12 CS11 CS10

Bit Name Bedeutung Möglichkeiten


Noise Canceler 0: ausgeschaltet, erste Flanke löst Sampling aus
7 ICNC1
am ICP-Pin 1: eingeschaltet, Mindestdauer vier Taktzyklen
Flankenauswahl 0: fallende Flanke löst Capture aus
6 ICES1
bei Capture 1: steigende Flanke löst Capture aus
5..4 (nicht benutzt)
Rücksetzen bei
3 CTC1 1: Zähler wird bei Gleichheit auf Null gesetzt
Compare Match A
000: Zähler anhalten
001: Clock
010: Clock / 8
011: Clock / 64
2..0 CS12..CS10 Taktauswahl
100: Clock / 256
101: Clock / 1024
110: fallende Flanke externer Pin T1
111: steigende Flanke externer Pin T1

Port Funktion Port-Adresse RAM-Adresse


TCNT1L/H Timer/Counter 1 Zählregister 0x2C/0x2D 0x4C/0x4D

Port Funktion Port-Adresse RAM-Adresse


OCR1AL/H Timer/Counter 1 Output Vergleichsregister A 0x2A/0x2B 0x4A/0x4B hex

Port Funktion Port-Adresse RAM-Adresse


OCR1BL/H Timer/Counter 1 Output Vergleichsregister B 0x28/0x29 0x48/0x49

Port Funktion Port-Adresse RAM-Adresse


ICR1L/H Timer/Counter 1 Input Capture Register 0x24/0x25 0x44/0x45

Zum Seitenanfang

Watchdog-Timer

Port Funktion Port-Adresse RAM-Adresse


WDTCR Watchdog Timer Control Register 0x21 0x41

7 6 5 4 3 2 1 0
- - - WDTOE WDE WDP2 WDP1 WDP0

Bit Name Bedeutung WDT-Zyklus bei 5,0Volt


7..5 (Nicht benutzt)
Vorausgehendes Setzen zum
4 WDTOE Watchdog Turnoff Enable
Abschalten von WDE erforderlich
3 WDE Watchdog Enable 1: Watchdog aktiv
000: 15 ms
001: 30 ms
010: 60 ms
011: 120 ms
2..0 WDP2..WDP0 Watchdog Timer Prescaler
100: 240 ms
101: 490 ms
110: 970 ms
111: 1,9 s

Zum Seitenanfang

EEPROM

Port Funktion Port-Adresse RAM-Adresse


EEARL/H EEPROM Adress Register 0x1E/0x1F 0x3E/0x3F
EEARH nur bei Typen mit mehr als 256 Bytes EEPROM (ab AT90S8515 aufwärts)

Port Funktion Port-Adresse RAM-Adresse


EEDR EEPROM Data Register 0x1D 0x3D

Port Funktion Port-Adresse RAM-Adresse


EECR EEPROM Control Register 0x1C 0x3C

7 6 5 4 3 2 1 0
- - - - - EEMWE EEWE EERE

Bit Name Bedeutung Funktion


7..3 (Nicht benutzt)
2 EEMWE EEPROM Master Write Enable Vorausgehendes Setzen ermöglicht Schreiben
1 EEWE EEPROM Write Enable Setzen löst Schreiben aus
0 EERE EEPROM Read Enable Setzen löst Auslesen aus

Zum Seitenanfang

Serial Peripheral Interface SPI

Port Funktion Port-Adresse RAM-Adresse


SPCR SPI Control Register 0x0D 0x2D

7 6 5 4 3 2 1 0
SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0

Bit Name Bedeutung Funktion


0: Interrupts disabled
7 SPIE SPI Interrupt Enable
1: Interrupts enabled
0: SPI abgeschaltet
6 SPE SPI Enable
1: SPI eingeschaltet
0: MSB zuerst
5 DORD Data Order
1: LSB zuerst
0: Slave
4 MSTR Master/Slave Select
1: Master
0: Positive Clock Phase
3 CPOL Clock Polarity
1: Negative Clock Phase
0: Sampling zu Beginn der Clock Phase
2 CPHA Clock Phase
1: Sampling am Ende der Clock Phase
00: Clock / 4
1 SPR1
01: Clock / 16
SCK Taktfrequenz
10: Clock / 64
0 SPR0
11: Clock / 128

Port Funktion Port-Adresse RAM-Adresse


SPSR SPI Status Register 0x0E 0x2E

7 6 5 4 3 2 1 0
SPIF WCOL - - - - - -

Bit Name Bedeutung Funktion


7 SPIF SPI Interrupt Flag Interruptanforderung
6 WCOL Write Collision Flag Schreibkollision aufgetreten
5..0 (Nicht benutzt)

Port Funktion Port-Adresse RAM-Adresse


SPDR SPI Data Register 0x0F 0x2F

Zum Seitenanfang

UART

Port Funktion Port-Adresse RAM-Adresse


UDR UART I/O Data Register 0x0C 0x2C

Port Funktion Port-Adresse RAM-Adresse


USR UART Status Register 0x0B 0x2B

7 6 5 4 3 2 1 0
RXC TXC UDRE FE OR - - -

Bit Name Bedeutung Funktion


7 RXC UART Receive Complete 1: Zeichen empfangen
6 TXC UART Transmit Complete 1: Schieberegister leer
5 UDRE UART Data Register Empty 1: Senderegister frei
4 FE Framing Error 1: Ungültiges Stop-Bit
3 OR Overrun 1: Zeichenverlust
2..0 (Nicht benutzt)

Port Funktion Port-Adresse RAM-Adresse


UCR UART Control Register 0x0A 0x2A

7 6 5 4 3 2 1 0
RXCIE TXCIE UDRIE RXEN TXEN CHR9 RXB8 TXB8

Bit Name Bedeutung Funktion


7 RXCIE RX Complete Interrupt Enable 1: Interrupt bei empfangenem Zeichen
6 TXCIE TX Complete Interrupt Enable 1: Interrupt bei leerem Senderschieberegister
5 UDRIE Data Register Empty Interrupt Enable 1: Interrupt bei leerem Senderegister
4 RXEN Receiver Enabled 1: Empfänger eingeschaltet
3 TXEN Transmitter Enable 1: Sender eingeschaltet
2 CHR9 9-bit Characters 1: Zeichen mit 9 Bit Länge
1 RXB8 Receive Data Bit 8 9.Datenbit beim Empfang
0 TXB8 Transmit Data Bit 8 9.Datenbit beim Senden

Port Funktion Port-Adresse RAM-Adresse


UBRR UART Baud Rate Register 0x09 0x29

Zum Seitenanfang

Analog Comparator

Port Funktion Port-Adresse RAM-Adresse


ACSR Analog Comparator Control and Status Register 0x08 0x28

7 6 5 4 3 2 1 0
ACD - ACO ACI ACIE ACIC ACIS1 ACIS0

Bit Name Bedeutung Funktion


7 ACD Disable Abschaltung des Comparators
6 (Nicht benutzt)
5 ACO Comparator Output Lesen: Ausgang des Comparators
4 ACI Interrupt Flag 1: Interruptanforderung
3 ACIE Interrupt Enable 1: Interrupts enabled
2 ACIC Input Capture Enable 1: Verbindung zu Timer 1 Capture
00: Interrupt bei Pegelwechsel
1 ACIS1
01: Nicht benutzt)
Input Capture Enable
10: Interrupt bei fallender Flanke
0 ACIS0
11: Interrupt bei steigender Flanke

Zum Seitenanfang

I/O Ports

Port Register Funktion Port-Adresse RAM-Adresse


PORTA Data Register 0x1B 0x3B
A DDRA Data Direction Register 0x1A 0x3A
PINA Input Pins Address 0x19 0x39
PORTB Data Register 0x18 0x38
B DDRB Data Direction Register 0x17 0x37
PINB Input Pins Address 0x16 0x36
PORTC Data Register 0x15 0x35
C DDRC Data Direction Register 0x14 0x34
PINC Input Pins Address 0x13 0x33
PORTD Data Register 0x12 0x32
D DDRD Data Direction Register 0x11 0x31
PIND Input Pins Address 0x10 0x30

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/pdetail.html1/20/2009 7:31:32 PM
Programmablaufsteuerung in AVR Assembler

Pfad: Home => AVR-Überblick => Programmiertechniken => Programmablauf

Programmiertechnik für Anfänger in AVR


Assemblersprache
Steuerung des Programmablaufes in AVR Assembler
Hier werden alle Vorgänge erläutert, die mit dem Programmablauf zu tun haben und diesen beeinflussen,
also die Vorgänge beim Starten des Prozessors, Sprünge und Verzweigungen, Unterbrechungen, etc.

Was passiert beim Reset?

Beim Anlegen der Betriebsspannung, also beim Start des Prozessors, wird über die Hardware des
Prozessors ein sogenannter Reset ausgelöst. Dabei wird der Zähler für die Programmschritte auf Null
gesetzt. An dieser Stelle des Programmes wird die Verarbeitung also immer begonnen. Ab hier muss der
Programm-Code stehen, der ausgeführt werden soll. Aber nicht nur beim Start wird der Zähler auf diese
Adresse zurückgesetzt, sondern auch bei

1. externem Rücksetzen am Eingangs-Pin Reset durch die Hardware,


2. Ablauf der Wachhund-Zeit (Watchdog-Reset), einer internen Überwachungsuhr,
3. direkten Sprüngen an die Adresse Null (Sprünge siehe unten).

Die dritte Möglichkeit ist aber gar kein richtiger Reset, denn das beim Reset automatisch ablaufende
Rücksetzen von Register- und Port-Werten auf den jeweils definierten Standardwert (Default) wird
hierbei nicht durchgeführt. Vergessen wir also besser die 3.Möglichkeit, sie ist unzuverlässig.

Die zweite Möglichkeit, nämlich der eingebaute Wachhund, muss erst explizit von der Leine gelassen
werden, durch Setzen seiner entsprechenden Port-Bits. Wenn er dann nicht gelegentlich mit Hilfe der
Instruktion

WDR

zurückgepfiffen wird, dann geht er davon aus, dass Herrchen AVR eingeschlafen ist und weckt ihn mit
einem brutalen Reset (Kaltstart).

Ab dem Reset wird also der an Adresse 0x000000 stehende Code wortweise in die Ausführungsmimik
des Prozessors geladen und ausgeführt. Während der Ausführung wird die Adresse um 1 erhöht und
schon mal die nächste Instruktion aus dem Programmspeicher geholt (Fetch during Execution). Wenn die
erste Instruktion keine Verzweigung des Programmes auslöst, kann die zweite Instruktion also direkt
nach dem ersten ausgeführt werden. Jeder Taktzyklus am Takteingang des Prozessors entspricht daher
einer ausgef&uum;hrten Instruktion (wenn nichts dazwischenkommt).

Die erste Instruktion des ausführbaren Programmes muss immer bei Adresse 0x000000 stehen. Um dem
Assembler mitzuteilen, dass er nach irgendwelchen Vorwörtern wie Definitionen oder Konstanten nun
bitte mit der ersten Zeile Programmcode beginnen möge, gibt es folgende Direktiven:

.CSEG
.ORG 0000

Die erste Direktive teilt dem Assembler mit, dass ab jetzt in das Code-Segment zu assemblieren ist. Ein
anderes Segment wäre z.B. das EEPROM, das ebenfalls im Assembler-Quelltext auf bestimmte Werte
eingestellt werden könnte. Die entsprechende Assembler-Direktive hierfür würde dann natürlich lauten:

.ESEG

Die zweite Assembler-Direktive oben stellt den Programmzähler beim Assemblieren auf die Adresse
0000 ein. ORG ist die Abkürzung für Origin, also Ursprung. Wir könnten auch bei 0100 mit dem
Programm beginnen, aber das wäre ziemlich sinnlos (siehe oben). Da die beiden Angaben CSEG und
ORG trivial sind, können sie auch weggelassen werden und der Assembler macht das dann automatisch
so. Wer aber den Beginn des Codes nach zwei Seiten Konstantendefinitionen eindeutig markieren will,
kann das mit den beiden Direktiven tun.

Auf das erste ominöse erste Wort Programmcode folgen fast ebenso wichtige Spezialbefehle, die
Interrupt-Vektoren. Dies sind festgelegte Stellen mit bestimmten Adressen. Diese Adressen werden bei
Auslösung eines Interrupts durch die Hardware angesprungen, wobei der normale Programmablauf
unterbrochen wird. Diese Vektoren sind spezifisch für jeden Prozessortyp (siehe unten bei der
Erläuterung der Interrupts). Die Instruktionen, mit denen auf eine Unterbrechung reagiert werden soll,
müssen an dieser Stelle stehen. Werden also Interrupts verwendet, dann kann die erste Instruktion nur
eine Sprunginstruktion sein, damit diese ominösen Vektoren übersprungen werden. Der typische
Programmablauf nach dem Reset sieht also so aus:

.CSEG
.ORG 0000
RJMP Start
[...] hier kommen dann die Interrupt-Vektoren
[...] und danach nach Belieben noch alles mögliche andere Zeug
Start: ; Das hier ist der Programmbeginn
[...] Hier geht das Hauptprogramm dann erst richtig los.

Die Instruktion RJMP bewirkt einen Sprung an die Stelle im Programm mit der Kennzeichnung Start:,
auch ein Label genannt. Die Stelle Start: folgt weiter unten im Programm und ist dem Assembler hiermit
entsprechend mitgeteilt: Labels beginnen immer in Spalte 1 einer Zeile und enden mit einem
Doppelpunkt. Labels, die diese beiden Bedingungen nicht einhalten, werden vom Assembler nicht
ernstgenommen. Fehlende Labels aber lassen den Assembler sinnierend innehalten und mit einer
"Undefined label"-Fehlermeldung die weitere Zusammenarbeit einstellen.

Zum Seitenanfang

Linearer Programmablauf und Verzweigungen

Nachdem die ersten Schritte im Programm gemacht sind, noch etwas triviales: Programme laufen linear
ab. Das heißt: Instruktion für Instruktion wird nacheinander aus dem Programmspeicher geholt und
abgearbeitet. Dabei zählt der Programmzähler immer eins hoch. Ausnahmen von dieser Regel werden
nur vom Programmierer durch gewollte Verzweigungen oder mittels Interrupt herbeigeführt. Da sind
Prozessoren ganz stur immer geradeaus, es sei denn, sie werden gezwungen.

Und zwingen geht am einfachsten folgendermaßen. Oft kommt es vor, dass in Abhängigkeit von
bestimmten Bedingungen gesprungen werden soll. Dann benötigen wir bedingte Verzweigungen.
Nehmen wir an, wir wollen einen 32-Bit-Zähler mit den Registern R1, R2, R3 und R4 realisieren. Dann
muss das niederwertigste Byte in R1 um Eins erhöht werden. Wenn es dabei überläuft, muss auch R2 um
Eins erhöht werden usw. bis R4.

Die Erhöhung um Eins wird mit der Instruktion INC erledigt. Wenn dabei ein Überlauf auftritt, also 255
zu 0 wird,
dann ist das
im Anschluss
an die
Durchführung
am gesetzten
Z-Bit im
Statusregister
zu bemerken.
Das
eigentliche
Übertragsbit
C des
Statusregisters
wird bei der
INC-
Instruktion
nicht
verändert,
weil es
woanders
dringender
gebraucht
wird und das
Z-Bit völlig
ausreicht.
Wenn der
Übertrag nicht
auftritt, also
das Z-Bit
nicht gesetzt
ist, können
wir die
Erhöherei
beenden.

Wenn aber das Z-Bit gesetzt ist, darf die Erhöherei beim nächsten Register weitergehen. Wir müssen also
springen, wenn das Z-Bit nicht gesetzt ist. Der entsprechende Sprungbefehl heißt aber nicht BRNZ
(BRanch on Not Zero), sondern BRNE (BRanch if Not Equal). Na ja, Geschmackssache. Das ganze
Räderwerk des 32-Bit langen Zählers sieht damit so aus:

INC R1
BRNE Weiter
INC R2
BRNE Weiter
INC R3
BRNE Weiter
INC R4
Weiter:

Das war es schon. Eine einfache Sache.Das Gegenteil von BRNE ist übrigens BREQ oder BRanch EQual.

Welche der Statusbits durch welche Instruktionen und Bedingungen gesetzt oder rückgesetzt werden
(auch Prozessorflags genannt), geht aus den einzelnen Instruktionsbeschreibungen in der Befehlsliste
hervor. Entsprechend kann mit den bedingten Sprunginstruktionen

BRCC/BRCS ; Carry-Flag 0 oder gesetzt


BRSH ; Gleich oder größer
BRLO ; Kleiner
BRMI ; Minus
BRPL ; Plus
BRGE ; Größer oder gleich (mit Vorzeichen)
BRLT ; Kleiner (mit Vorzeichen)
BRHC/BRHS ; Halbübertrag 0 oder 1
BRTC/BRTS ; T-Bit 0 oder 1
BRVC/BRVS ; Zweierkomplement-Übertrag 0 oder 1
BRIE/BRID ; Interrupt an- oder abgeschaltet

auf die verschiedenen Bedingungen reagiert werden. Gesprungen wird immer dann, wenn die
entsprechende Bedingung erfüllt ist. Keine Angst, die meisten dieser Instruktionen braucht man sehr
selten. Nur Zero und Carry sind für den Anfang wichtig.

Zum Seitenanfang

Zeitzusammenhänge beim Programmablauf

Wie oben schon erwähnt entspricht die Zeitdauer zur Bearbeitung einer Instruktion in der Regel exakt
einem Prozessortakt. Läuft der Prozessor mit 4 MHz Takt, dann dauert die Bearbeitung einer Instruktion
1/4 µs oder 250 ns, bei 10 MHz Takt nur 100 ns. Die Dauer ist quarzgenau vorhersagbar und
Anwendungen, die ein genaues Timing erfordern, sind durch entsprechend exakte Gestaltung des
Programmablaufes erreichbar. Es gibt aber eine Reihe von Instruktionen, z.B. die Sprungbefehle oder die
Lese- und Schreibbefehle für das SRAM, die zwei oder mehr Taktzyklen erfordern. Hier hilft nur die
Instruktionstabelle weiter.

Um genaue Zeitbeziehungen herzustellen, muss man manchmal den Programmablauf um eine bestimmte
Anzahl Taktzyklen verzögern. Dazu gibt es die sinnloseste Instruktion des Prozessors, den Tu-nix-Befehl:

NOP

Diese Instruktion heißt "No Operation" und tut nichts außer Prozessorzeit zu verschwenden. Bei 4 MHz
Takt braucht es genau vier solcher NOPs, um eine exakte Verzögerung um 1 µs zu erreichen. Zu viel
anderem ist diese Instruktion nicht zu gebrauchen. Für einen Rechteckgenerator von 1 kHz müssen aber
nicht 1000 solcher NOPs kopiert werden, das geht auch anders! Dazu braucht es die
Sprunginstruktionen. Mit ihrer Hilfe können Schleifen programmiert werden, die für eine festgelegte
Anzahl von Läufen den Programmablauf aufhalten und verzögern. Das können 8-Bit-Register sein, die
mit der DEC-Instruktion heruntergezählt werden, wie z.B. bei

CLR R1
Zaehl:
DEC R1
BRNE Zaehl

Es können aber auch 16-Bit-Zähler sein, wie z.B. bei

LDI ZH,HIGH(65535)
LDI ZL,LOW(65535)
Zaehl:
SBIW ZL,1
BRNE Zaehl

Mit mehr Registern lassen sich mehr Verzögerungen erreichen. Jeder dieser Verzögerer kann auf den
jeweiligen Bedarf eingestellt werden und funktioniert dann quarzgenau, auch ohne Hardware-Timer.

Zum Seitenanfang

Makros im Programmablauf

Es kommt vor, dass in einem Programm identische oder ähnliche Code-Sequenzen an mehreren Stellen
benötigt werden. Will oder kann man den Programmteil nicht mittels Unterprogrammen bewältigen,
dann kommt für diese Aufgabe auch ein Makro in Frage. Makros sind Codesequenzen, die nur einmal
entworfen werden und durch Aufruf des Makronamens in den Programmablauf eingefügt werden.
Nehmen wir an, es soll die folgende Codesequenz (Verzögerung um 1 µs bei 4 MHz Takt) an mehreren
Programmstellen benötigt werden. Dann erfolgt irgendwo im Quellcode die Definition des folgenden
Makros:

.MACRO Delay1
NOP
NOP
NOP
NOP
.ENDMACRO

Diese Definition des Makros erzeugt keinen Code, es werden also keine vier NOPs in den Code
eingefügt. Erst der Aufruf des Makros

[...] irgendwo im Code


Delay1
[...] weiter mit Code

bewirkt, dass an dieser Stelle vier NOPs eingebaut werden. Der zweimalige Aufruf des Makros baut acht
NOPs in den Code ein.

Handelt es sich um größere Codesequenzen, hat man etwas Zeit im Programm oder ist man knapp mit
Programmspeicher, sollte man auf den Code-extensiven Einsatz von Makros verzichten und lieber
Unterprogramme verwenden.

Zum Seitenanfang

Unterprogramme

Im Gegensatz zum Makro geht ein Unterprogramm sparsamer mit dem Programmspeicher um. Irgendwo
im Code steht die Sequenz ein einziges Mal herum und kann von verschiedenen Programmteilen her
aufgerufen werden. Damit die Verarbeitung des Programmes wieder an der aufrufenden Stelle
weitergeht, folgt am Ende des Unterprogrammes ein Return. Das sieht dann für 10 Takte Verzögerung so
aus:

Delay10:
NOP
NOP
NOP
RET

Unterprogramme beginnen immer mit einem Label, hier Delay10:, weil sie sonst nicht angesprungen
werden könnten. Es folgen drei Nix-Tun-Instruktionen und die abschließende Return-Instruktion.
Schlaumeier könnten jetzt einwenden, das seien ja bloß 7 Takte (RET braucht 4) und keine 10. Gemach,
es kömmt noch der Aufruf dazu und der schlägt mit 3 Takten zu Buche:

[...] irgendwo im Programm:


RCALL Delay10
[...] weiter im Programm

RCALL ist eine Verzweigung zu einer relativen Adresse, nämlich zum Unterprogramm. Mit RET wird
wieder der lineare Programmablauf abgebrochen und zu der Instruktion nach dem RCALL verzweigt. Es
sei noch dringend daran erinnert, dass die Verwendung von Unterprogrammen das vorherige Setzen des
Stackpointers oder Stapelzeigers voraussetzt (siehe Stapel), weil die Rücksprungadresse beim RCALL
auf dem Stapel abgelegt wird.

Wer das obige Beispiel ohne Stapel programmieren möchte, verwendet den absoluten Sprungbefehl:

[...] irgendwo im Programm


RJMP Delay10
Zurueck:
[...] weiter im Programm

Jetzt muss das "Unterprogramm" allerdings anstelle des RET natürlich ebenfalls eine RJMP-Instruktion
bekommen und zum Label Zurueck: verzweigen. Da der Programmcode dann aber nicht mehr von
anderen Stellen im Programmcode aufgerufen werden kann (die Rückkehr funktioniert jetzt nicht mehr),
ist die Springerei ziemlich sinnlos. Auf jeden Fall haben wir jetzt das relative Springen mit RJMP gelernt.

RCALL und RJMP sind auf jeden Fall unbedingte Verzweigungen. Ob sie ausgeführt werden hängt nicht
von irgendwelchen Bedingungen ab. Zum bedingten Ausführen eines Unterprogrammes muss das
Unterprogramm mit einem bedingten Verzweigungsbefehl kombiniert werden, der unter bestimmten
Bedingungen das Unterprogramm ausführt oder den Aufruf eben überspringt. Für solche bedingten
Verweigungen zu einem Unterprogramm eignen sich die beiden folgenden Instruktionen ideal. Soll in
Abhängigkeit vom Zustand eines Bits in einem Register zu einem Unterprgramm oder einem anderen
Programmteil verzweigt werden, dann geht das so:

SBRC R1,7 ; Überspringe wenn Bit 7 Null ist


RCALL UpLabel ; Rufe Unterprogramm auf

Hier wird der RCALL zum Unterprogramm UpLabel: nur ausgeführt, wenn das Bit 7 im Register R1 eine
Eins ist, weil die Instruktion bei einer Null (Clear) übersprungen wird. Will man auf die umgekehrte
Bedingung hin ausführen, so kommt statt SBRC die analoge Instruktion SBRS zum Einsatz. Die auf
SBRC/SBRS folgende Instruktion kann sowohl eine Ein-Wort- als auch eine Zwei-Wort-Instruktion sein,
der Prozessor weiß die Länge der Instruktion korrekt Bescheid und überspringt dann eben um die richtige
Anzahl Instruktionen. Zum Überspringen von mehr als einer Instruktion kann dieser bedingte Sprung
natürlich nicht benutzt werden.

Soll ein Überspringen nur dann erfolgen, wenn zwei Registerinhalte gleich sind, dann bietet sich die
etwas exotische Instruktion

CPSE R1,R2 ; Vergleiche R1 und R2, springe wenn gleich


RCALL UpIrgendwas ; Rufe irgendwas

Der wird selten gebraucht und ist ein Mauerblümchen.

Man kann aber auch in Abhängigkeit von bestimmten Port-Bits die nächsten Instruktion überspringen.
Die entsprechenden Instruktionen heißen SBIC und SBIS, also etwa so:

SBIC PINB,0 ; Überspringe wenn Bit 0 Null ist


RJMP EinZiel ; Springe zum Label EinZiel

Hier wird die RJMP-Instruktion nur übersprungen, wenn das Bit 0 im Eingabeport PINB gerade Null ist.
Also wird das Programm an dieser Stelle nur dann zum Programmteil EinZiel: verzweigen, wenn das
Portbit 0 Eins ist. Das ist etwas verwirrend, da die Kombination von SBIC und RJMP etwas umgekehrt
wirkt als sprachlich naheliegend ist. Das umgekehrte Sprungverhalten kann anstelle von SBIC mit SBIS
erreicht werden. Leider kommen als Ports bei den beiden Instruktionen nur die unteren 32 infrage, für die
oberen 32 Ports können diese Instruktionen nicht verwendet werden.

Nun noch die Exotenanwendung für den absoluten Spezialisten. Nehmen wir mal an, sie hätten vier
Eingänge am AVR, an denen ein Bitklavier angeschlossen sei (vier kleine Schalterchen). Je nachdem,
welches der vier Tasten eingestellt sei, soll der AVR 16 verschiedene Tätigkeiten vollführen. Nun
könnten Sie selbstverständlich den Porteingang lesen und mit jede Menge Branch-Anweisungen schon
herausfinden, welches der 16 Programmteile denn heute gewünscht wird. Sie können aber auch eine
Tabelle mit je einem Sprungbefehl auf die sechzehn Routinen machen, etwa so:

MeinTab:
RJMP Routine1
RJMP Routine2
[...]
RJMP Routine16

Jetzt laden Sie den Anfang der Tabelle in das Z-Register mit

LDI ZH,HIGH(MeinTab)
LDI ZL,LOW(MeinTab)

und addieren den heutigen Pegelstand am Portklavier in R16 zu dieser Adresse.

ADD ZL,R16
BRCC NixUeberlauf
INC ZH
NixUeberlauf:

Jetzt können Sie nach Herzenslust und voller Wucht in die Tabelle springen, entweder nur mal als
Unterprogramm mit

ICALL

oder auf Nimmerwiederkehr mit

IJMP

Der Prozessor lädt daraufhin den Inhalt seines Z-Registerpaares in den Programmzähler und macht dort
weiter. Manche finden das eleganter als unendlich verschachtelte bedingte Sprünge. Mag sein.

Zum Seitenanfang

Interrupts im Programmablauf

Sehr oft kommt es vor, dass in Abhängigkeit von irgendwelchen Änderungen in der Hardware oder zu
bestimmten Gelegenheiten auf dieses Ereignis reagiert wird. Ein Beispiel ist die Pegeländerung an einem
Eingang. Man kann das lösen, indem das Programm im Kreis herum läuft und immer den Eingang
befragt, ob er sich nun geändert hat. Die Methode heisst Polling, weil es wie bei die Bienchen darum
geht, jede Blüte immer mal wieder zu besuchen und deren neue Pollen einzusammeln. Gibt es ausser
diesem Eingang noch anderes wichtiges für den Prozessor zu tun, dann kann das dauernde
zwischendurch Anfliegen der Blüte ganz schön nerven und sogar versagen: Kurze Pulse werden nicht
erkannt, wenn Bienchen nicht gerade vorbei kam und nachsah, der Pegel aber wieder weg ist. Für diesen
Fall hat man den Interrupt erfunden.

Der Interrupt ist eine von der Hardware ausgelöste Unterbrechung des Programmablaufes. Dazu kriegt
das Gerät zunächst mitgeteilt, dass es unterbrechen darf. Dazu ist bei dem entsprechenden Gerät ein oder
mehr Bits in bestimmten Ports zu setzen. Dem Prozessor ist durch ein gesetztes Interrupt Enable Bit in
seinem Status-Register mitzuteilen, dass er unterbrochen werden darf. Irgendwann nach den
Anfangsfeierlichkeiten des Programmes muss dazu das I-Flag im Statusregister gesetzt werden, sonst
macht der Prozessor beim Unterbrechen nicht mit.

SEI ; Setze Int-Enable

Wenn jetzt die Bedingung eintritt, also z.B. ein Pegel von Null auf Eins wechselt, dann legt der Prozessor
seine aktuelle Programmadresse erst mal auf den Stapel ab (Obacht! Der muss vorher eingerichtet sein!
Wie das geht siehe Stapel). Er muss ja das unterbrochene Programm exakt an der Stelle wieder
aufnehmen, an dem es unterbrochen wurde, dafür der Stapel. Nun springt der Prozessor an eine
vordefinierte Stelle des Programmes und setzt die Verarbeitung erst mal dort fort. Die Stelle nennt man
Interrupt Vektor. Sie ist prozessorspezifisch festgelegt. Da es viele Geräte gibt, die auf unterschiedliche
Ereignisse reagieren können sollen, gibt es auch viele solcher Vektoren. So hat jede Unterbrechung ihre
bestimmte Stelle im Programm, die angesprungen wird. Die entsprechenden Programmstellen der
wichtigsten Prozessoren sind in der folgenden Tabelle aufgelistet. (Der erste Vektor ist aber kein Int-
Vektor, weil er keine Rücksprung-Adresse auf dem Stapel ablegt!)

Int Vector Adresse


Name ausgelöst durch ...
2313 2323 8515
RESET 0000 0000 0000 Hardware Reset, Power-On Reset, Watchdog Reset
INT0 0001 0001 0001 Pegelwechsel am externen INT0-Pin
INT1 0002 - 0002 Pegelwechsel am externen INT1-Pin
TIMER1 CAPT 0003 - 0003 Fangschaltung am Timer 1
TIMER1 COMPA - - 0004 Timer1 = Compare A
TIMER1 COMPB - - 0005 Timer1 = Compare B
TIMER1 COMP1 0004 - - Timer1 = Compare 1
TIMER1 OVF 0005 - 0006 Timer1 Überlauf
TIMER0 OVF 0006 0002 0007 Timer0 Überlauf
SPI STC - - 0008 Serielle Übertragung komplett
UART RX 0007 - 0009 UART Zeichen im Empfangspuffer
UART UDRE 0008 - 000A UART Senderegister leer
UART TX 0009 - 000B UART Alles gesendet
ANA_COMP - - 000C Analog Comparator

Man erkennt, dass die Fähigkeit, Interrupts auszulösen, sehr unterschiedlich ausgeprägt ist. Sie entspricht
der Ausstattung der Chips mit Hardware. Die Adressen folgen aufeinander, sind aber für den Typ
spezifisch durchnumeriert. Die Reihenfolge hat einen weiteren Sinn: Je höher in der Liste, desto
wichtiger. Wenn also zwei Geräte gleichzeitig die Unterbrechung auslösen, gewinnt die jeweils obere in
der Liste. Die niedrigerwertige kommt erst dran, wenn die höherwertige fertig bearbeitet ist. Damit das
funktioniert, schaltet der erfolgreiche Interrupt das Interrupt-Status-Bit aus. Dann kann der niederwertige
erst mal verhungern. Erst wenn das Interrupt-Status-Bit wieder angeschaltet wird, kann die nächste
anstehende Unterbrechung ihren Lauf nehmen.

Für das Setzen des Statusbits kann die Unterbrechungsroutine, ein Unterprogramm, zwei Wege
einschlagen. Es kann am Ende mit der Instruktion

RETI

abschließen. Diese Instruktion stellt den ursprünglichen Befehlszähler wieder her, der vor der
Unterbrechung gerade bearbeitet werden sollte und setzt das Interrupt-Status-Bit auf Eins. Der zweite
Weg ist das Setzen des Status-Bits per Instruktion

SEI ; Setze Interrupt Enabled


RET ; Kehre zurück

und das Abschließen der Unterbrechungsroutine mit einem normalen RET. Aber Obacht, das ist nicht
identisch im Verhalten! Im zweiten Fall tritt die noch immer anstehende Unterbrechung schon ein, bevor
die anschließende Return-Instruktion bearbeitet wird, weil das Status-Bit schon um eine Instruktion
früher wieder Ints zulässt. Das führt zu einem Zustand, der das überragende Stapelkonzept so richtig
hervorhebt: ein verschachtelter Interrupt. Die Unterbrechung während der Unterbrechung packt wieder
die Rücksprung-Adresse auf den Stapel (jetzt liegen dort zwei Adressen herum), bearbeitet die
Unterbrechungsroutine für den zweiten Interrupt und kehrt an die oberste Adresse auf dem Stapel zurück.
Die zeigt auf die noch verbliebenen RET-Instruktion, die jetzt erst bearbeitet wird. Diese nimmt nun auch
die noch verbliebene Rücksprung-Adresse vom Stapel und kehrt zur Originaladresse zurück, die zur Zeit
der Unterbrechung zur Bearbeitung gerade anstand. Durch die LIFO-Stapelei ist das Verschachteln
solcher Aufrufe über mehrere Ebenen kein Problem, solange der Stapelzeiger noch richtiges SRAM zum
Ablegen vorfindet. Folgen allerdings zu viele Interrupts, bevor der vorherige richtig beendet wurde, dann
kann der Stapel auf dem SRAM überlaufen. Aber das muss man schon mit Absicht programmieren, weil
es doch sehr selten vorkommt.

Klar ist auch, dass an der Adresse des Int-Vektors nur für eine Ein-Wort-Instruktion Platz ist. Das ist in
der Regel eine RJMP-Instruktion an die Adresse des Interrupt Unterprogrammes. Es kann auch einfach
eine RETI-Instruktion sein, wenn dieser Vektor gar nicht benötigt wird. Wegen der Notwendigkeit, die
Interrupts möglichst rasch wieder freizugeben, damit der nächste anstehende Int nicht völlig aushungert,
sollten Interrupt-Service-Routinen nicht allzu lang sein. Lange Prozeduren sollten unbedingt die zweite
Methode zur Wiederherstellung des I-Bits wählen, also sofort nach Abarbeitung der zeitkritischen
Schritte die Interrupts mit SEI wieder vorzeitig zulassen, bevor die Routine ganz abgearbeitet ist.

Eine ganz, ganz wichtige Regel sollte in jedem Fall eingehalten werden: Die erste Instruktion einer
Interrupt-Service-Routine ist die Rettung des Statusregisters auf dem Stapel oder in einem Register. Die
letzte Instruktion der Routine ist die Wiederherstellung desselben in den Originalzustand vor der
Unterbrechung. Jede Instruktion in der Unterbrechungsroutine, die irgendeines der Flags (außer dem I-
Bit) verändert, würde unter Umständen verheerende Nebenfolgen auslösen, weil im unterbrochenen
Programmablauf plötzlich irgendeins der verwendeten Flags anders wird als an dieser Stelle im
Programmablauf vorgesehen, wenn die Interrupt-Service Routine zwischendurch zugeschlagen hat. Das
ist auch der Grund, warum alle verwendeten Register in Unterbrechungsroutinen entweder gesichert und
am Ende der Routine wiederhergestellt werden müssen oder aber speziell nur für die Int-Routinen
reserviert sein müssen. Sonst wäre nach einer irgendwann auftretenden Unterbrechung für nichts mehr zu
garantieren. Es ist nichts mehr so wie es war vor der Unterbrechung. Weil das alles so wichtig ist, hier
eine ausführliche beispielhafte Unterbrechungsroutine.

.CSEG ; Hier beginnt das Code-Segment


.ORG 0000 ; Die Adresse auf Null
RJMP Start ; Der Reset-Vektor an die Adresse 0000
RJMP IService ; 0001: erster Interrupt-Vektor, INT0 service routine
[...] hier eventuell weitere Int-Vektoren

Start: ; Hier beginnt das Hauptprogramm


[...] hier kann alles mögliche stehen

IService: ; Hier beginnt die Interrupt-Service-Routine


PUSH R16 ; Benutztes Register auf den Stapel
IN R16,SREG ; Statusregister Zustand einlesen
PUSH R16 ; ebenfalls auf den Stapel ablegen
[...] Hier macht die Int-Service-Routine irgendwas, benutzt Register R16
POP R16 ; alten Inhalt von SREG vom Stapel holen
OUT SREG,R16 ; und Statusregister wiederherstellen
POP R16 ; alten Inhalt von R16 wiederherstellen
RETI ; und zurückkehren

Das klingt alles ziemlich umständlich, ist aber wirklich lebenswichtig für korrekt arbeitende Programme.
Es vereinfacht sich entsprechend nur dann, wenn man Register satt zur Verfügung hat und wegen
exklusiver Nutzung durch die Service- Routine auf das Sichern verzichten kann.

Das war für den Anfang alles wirklich wichtige über Interrupts. Es gäbe noch eine Reihe von Tips, aber
das würde für den Anfang etwas zu verwirrend.

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/sprung.html1/20/2009 7:31:41 PM
Rechnen in AVR Assembler

Pfad: Home => AVR-Überblick => Programmiertechniken => Rechnen

Programmiertechnik für Anfänger in AVR


Assemblersprache
Rechnen in Assemblersprache
Hier gibt es alles Wichtige zum Rechnen in Assembler. Dazu gehören die gebräuchlichen
Zahlensysteme, das Setzen und Rücksetzen von Bits, das Schieben und Rotieren, das Addieren/
Subtrahieren/Vergleichen und die Umwandlung von Zahlen.

Zahlenarten in Assembler

An Darstellungsarten für Zahlen in Assembler kommen infrage:

● Positive Ganzzahlen,
● Vorzeichenbehaftete ganze Zahlen,
● Binary Coded Digit, BCD,
● Gepackte BCD,
● ASCII-Format.

Positive Ganzzahlen

Die kleinste handhabbare positive Ganzzahl in Assembler ist das Byte zu je acht Bits. Damit sind
Zahlen zwischen 0 und 255 darstellbar. Sie passen genau in ein Register des Prozessors. Alle
größeren Ganzzahlen müssen auf dieser Einheit aufbauen und sich aus mehreren solcher Einheiten
zusammensetzen. So bilden zwei Bytes ein Wort (Bereich 0 .. 65.535), drei Bytes ein längeres Wort
(Bereich 0 .. 16.777.215) und vier Bytes ein Doppelwort (Bereich 0 .. 4.294.967.295).

Die einzelnen Bytes eines Wortes oder Doppelwortes können über Register verstreut liegen, da zur
Manipulation ohnehin jedes einzelne Register in seiner Lage angegeben sein muss. Damit wir den
Überblick nicht verlieren, könnte z.B. ein Doppelwort so angeordnet sein:

.DEF dw0 = r16


.DEF dw1 = r17
.DEF dw2 = r18
.DEF dw3 = r19

dw0 bis dw3 liegen jetzt in einer Registerreihe. Soll dieses Doppelwort z.B. zu Programmbeginn auf
einen festen Wert (hier: 4.000.000) gesetzt werden, dann sieht das in Assembler so aus:

.EQU dwi = 4000000 ; Definieren der Konstanten


LDI dw0,LOW(dwi) ; Die untersten 8 Bits in R16
LDI dw1,BYTE2(dwi) ; Bits 8 .. 15 in R17
LDI dw2,BYTE3(dwi) ; Bits 16 .. 23 in R18
LDI dw3,BYTE4(dwi) ; Bits 24 .. 31 in R19

Damit ist die Zahl in verdauliche Brocken auf die Register aufgeteilt und es darf mit dieser Zahl
gerechnet werden.

Zum Seitenanfang

Vorzeichenbehaftete Zahlen

Manchmal, aber sehr selten, braucht man auch negative Zahlen zum Rechnen. Die kriegt man
definiert, indem das höchstwertigste Bit eines Bytes als Vorzeichen interpretiert wird. Ist es Eins,
dann ist die Zahl negativ. In diesem Fall werden alle Zahlenbits mit ihrem invertierten Wert
dargestellt. Invertiert heißt, dass -1 zu binär 1111.1111 wird, die 1 also als von binär 1.0000.0000
abgezogen dargestellt wird. Das vorderste Bit ist dabei aber das Vorzeichen, das signalisiert, dass die
Zahl negativ ist und die folgenden Bits die Zahl invertiert darstellen. Einstweilen genügt es zu
verstehen, dass beim binären Addieren von +1 (0000.0001) und -1 (1111.1111) ziemlich exakt Null
herauskommt, wenn man von dem gesetzten Übertragsbit Carry mal absieht.

In einem Byte sind mit dieser Methode die Ganzzahlen von +127 (binär: 0111.1111) bis -128 (binär:
1000.000) darstellbar. In Hochsprachen spricht man von Short-Integer. Benötigt man größere
Zahlenbereiche, dann kann man weitere Bytes hinzufügen. Dabei enthält nur das jeweils
höchstwertigste Byte das Vorzeichenbit für die gesamte Zahl. Mit zwei Bytes ist damit der
Wertebereich von +32767 bis -32768 (Hochsprachen: Integer), mit vier Bytes der Wertebereich von
+2.147.483.647 bis -2.147.483.648 darstellbar (Hochsprachen: LongInt).

Zum Seitenanfang

Binary Coded Digit, BCD

Die beiden vorgenannten Zahlenarten nutzen die Bits der Register optimal aus, indem sie die Zahlen
in binärer Form behandeln. Man kann Zahlen aber auch so darstellen, dass auf ein Byte nur jeweils
eine dezimale Ziffer kommt. Eine dezimale Ziffer wird dazu in binärer Form gespeichert. Da die
Ziffern von 0 bis 9 mit vier Bits darstellbar sind und selbst in den vier Bits noch Luft ist (in vier Bits
würde dezimal 0 .. 15 passen), bleibt dabei ziemlich viel Raum leer. Für das Speichern der Zahl 250
werden schon drei Register gebraucht, also z.B. so:
Bit 7 6 5 4 3 2 1 0
Instruktionen zum Setzen:
Wertigkeit 128 64 32 16 8 4 2 1 LDI R16,2
R16, Ziffer 1 0 0 0 0 0 0 1 0 LDI R17,5
LDI R18,0
R17, Ziffer 2 0 0 0 0 0 1 0 1
R18, Ziffer 3 0 0 0 0 0 0 0 0

Auch mit solchen Zahlenformaten lässt sich rechnen, nur ist es aufwendiger als bei den binären
Formen. Der Vorteil ist, dass solche Zahlen mit fast beliebiger Größe (soweit das SRAM reicht ...)
gehandhabt werden können und dass sie leicht in Zeichenketten umwandelbar sind.

Zum Seitenanfang

Gepackte BCD-Ziffern

Nicht ganz so verschwenderisch geht gepacktes BCD mit den Ziffern um. Hier wird jede binär
kodierte Ziffer in jeweils vier Bits eines Bytes gepackt, so dass ein Byte zwei Ziffern aufnehmen
kann. Die beiden Teile des Bytes werden oberes und unteres Nibble genannt. Packt man die
höherwertige Ziffer in die oberen vier Bits des Bytes (Bit 4 bis 7), dann hat das beim Rechnen
Vorteile (es gibt spezielle Einrichtungen im AVR zum Rechnen mit gepackten BCD-Ziffern). Die
schon erwähnte Zahl 250 würde im gepackten BCD-Format folgendermaäßen aussehen:
Byte Ziffern Wert 8 4 2 1 8 4 2 1
Instruktionen zum Setzen:
2 4 und 3 02 0 0 0 0 0 0 1 0 LDI R17,0x02 ; Oberes Byte
1 2 und 1 50 0 1 0 1 0 0 0 0 LDI R16,0x50 ; Unteres Byte

Zum Setzen ist nun die binäre (0b...) oder die headezimale (0x...) Schreibweise erforderlich, damit
die Bits an die richtigen Stellen im oberen Nibble kommen.

Das Rechnen mit gepackten BCD ist etwas umständlicher im Vergleich zum Binär-Format, die
Zahlenumwandlung in darstellbare Zeichenketten aber fast so einfach wie im ungepackten BCD-
Format. Auch hier lassen sich fast beliebig lange Zahlen handhaben.

Zum Seitenanfang

Zahlen im ASCII-Format

Sehr eng verwandt mit dem ungepackten BCD-Format ist die Speicherung von Zahlen im ASCII-
Format. Dabei werden die Ziffern 0 bis 9 mit ihrer ASCII-Kodierung gespeichert (ASCII = American
Standard Code for Information Interchange). Das ist ein uraltes, aus Zeiten des mechanischen
Fernschreibers stammendes, sehr umständliches, äußerst beschränktes und von höchst innovativen
Betriebssystem-Herstellern in das Computer-Zeitalter herüber gerettetes sieben-bittiges Format, mit
dem zusätzlich zu irgendwelchen Befehlen der Übertragungssteuerung beim Fernschreiber (z.B. EOT
= End Of Transmission) auch Buchstaben und Zahlen darstellbar sind. Es wird in seiner
Altertümlichkeit nur noch durch den (ähnlichen) fünfbittigen Baudot-Code für deutsche
Fernschreiber und durch den Morse-Code für ergraute Marinefunker übertroffen. In diesem Code-
System wird die 0 durch die dezimale Ziffer 48 (hexadezimal: 30, binär: 0011.0000), die 9 durch die
dezimale Ziffer 57 (hexadezimal: 39, binär: 0011.1001) repräsentiert. Auf die Idee, diese Ziffern ganz
vorne im ASCII hinzulegen, hätte man schon kommen können, aber da waren schon die wichtigen
Verkehrs-Steuerzeichen für den Fernschreiber. So müssen wir uns noch immer damit herumschlagen,
48 zu einer BCD-kodierten Ziffer hinzu zu zählen oder die Bits 4 und 5 auf eins zu setzen, wenn wir
den ASCII-Code über die serielle Schnittstelle senden wollen. Zur Platzverschwendung gilt das schon
zu BCD geschriebene. Zum Laden der Zahl 250 kommt diesmal der folgende Quelltext zum Tragen:

LDI R18,'2'
LDI R17,'5'
LDI R16,'0'

Das speichert direkt die ASCII-Kodierung in das jeweilige Register.

Zum Seitenanfang

Bitmanipulationen

Um eine BCD-kodierte Ziffer in ihr ASCII-Pendant zu verwandeln, müssen die Bits 4 und 5 der Zahl
auf Eins gesetzt werden. Das verlangt nach einer binären Oder-Verknüpfung und ist eine leichte
Aufgabe. Die geht so (ORI geht nur mit Registern ab R16 aufwärts):

ORI R16,0x30

Steht ein Register zur Verfügung, in dem bereits 0x30 steht, hier R2, dann kann man das Oder auch
mit diesem Register durchführen:

OR R1,R2

Zurück ist es schon schwieriger, weil die naheliegende, umgekehrt wirkende Instruktion,

ANDI R1,0x0F

die die oberen vier Bits des Registers auf Null setzt und die unteren vier Bits beibeh•lt, nur für
Register oberhalb R15 möglich ist. Eventuell also in einem solchen Register durchführen!

Hat man die 0x0F schon in Register R2, kann man mit diesem Register Und-verknüpfen:

AND R1,R2

Auch die beiden anderen Instruktionen zur Bitmanipulation, CBR und SBR, lassen sich nur in
Registern oberhalb von R15 durchführen. Sie würden entsprechend korrekt lauten:

SBR R16,0b00110000 ; Bits 4 und 5 setzen


CBR R16,0b00110000 ; Bits 4 und 5 löschen

Sollen eins oder mehrere Bits einer Zahl invertiert werden, bedient man sich gerne des Exklusiv-
Oder-Verfahrens, das nur für Register, nicht für Konstanten, zulässig ist:

LDI R16,0b10101010 ; Invertieren aller geraden Bits


EOR R1,R16 ; in Register R1 und speichern in R1

Sollen alle Bits eines Bytes invertiert werden, kommt das Einer-Komplement ins Spiel. Mit

COM R1

wird der Inhalt eines Registers bitweise invertiert, aus Einsen werden Nullen und umgekehrt. So wird
aus 1 die Zahl 254, aus 2 wird 253, usw. Anders ist die Erzeugung einer negativen Zahl aus einer
Positiven. Hierbei wird das Vorzeichenbit (Bit 7) umgedreht bzw. der Inhalt von Null subtrahiert.
Dieses erledigt die Instruktion

NEG R1

So wird aus +1 (dezimal: 1) -1 (binär 1111.1111), aus +2 wird -2 (binär 1111.1110), usw.

Neben der Manipulation gleich mehrerer Bits in einem Register gibt es das Kopieren eines einzelnen
Bits aus dem eigens für diesen Zweck eingerichteten T-Bit des Status-Registers. Mit

BLD R1,0

wird das T-Bit im Statusregister in das Bit 0 des Registers R1 kopiert und das dortige Bit
überschrieben. Das T-Bit kann vorher auf Null oder Eins gesetzt oder aus einem beliebigen anderen
Bit-Lagerplatz in einem Register geladen werden:

CLT ; T-Bit auf Null setzen, oder


SET ; T-Bit auf Eins setzen, oder
BST R2,2 ; T-Bit aus Register R2, Bit 2, laden

Zum Seitenanfang

Schieben und Rotieren

Das Schieben von binären Zahlen entspricht dem Multiplizieren und Dividieren mit 2. Beim
Schieben gibt es unterschiedliche Mechanismen.

Die Multiplikation einer Zahl mit 2 geht einfach so vor sich, dass alle Bits einer binären Zahl um eine
Stelle nach links geschoben werden. In das freie Bit 0 kommt eine Null. Das überzählige ehemalige
Bit 7 wird dabei in das Carry-Bit im Status-Register abgeschoben. Der Vorgang wird logisches Links-
Schieben genannt.

LSL R1

Das umgekehrte Dividieren durch 2 heißt Dividieren oder logisches Rechts-Schieben.

LSR R1

Dabei wird das frei werdende Bit 7 mit einer 0 gefüllt, während das Bit 0 in das Carry geschoben
wird. Dieses Carry kann dann zum Runden der Zahl verwendet werden. Als Beispiel wird eine Zahl
durch vier dividiert und dabei gerundet.

LSR R1 ; Division durch 2


BRCC Div2 ; Springe wenn kein Runden
INC R1 ; Aufrunden
Div2:
LSR R1 ; Noch mal durch 2
BRCC DivE ; Springe wenn kein Runden
INC R1 ; Aufrunden
DivE:

Teilen ist also eine einfache Angelegenheit bei Binärzahlen (aber nicht durch 3)!

Bei Vorzeichen behafteten Zahlen würde das Rechtsschieben das Vorzeichen in Bit 7 übel verändern.
Das darf nicht sein. Desdewegen gibt es neben dem logischen Rechtsschieben auch das arithmetische
Rechtsschieben. Dabei bleibt das Vorzeichenbit 7 erhalten und die Null wird in Bit 6 eingeschoben.

ASR R1

Wie beim logischen Schieben landet das Bit 0 im Carry.

Wie nun, wenn wir 16-Bit-Zahlen mit 2 multiplizieren wollen? Dann muss das links aus dem
untersten Byte herausgeschobene Bit von rechts in das oberste Byte hineingeschoben werden. Das
erledigt man durch Rollen. Dabei landet keine Null im Bit 0 des verschobenen Registers, sondern der
Inhalt des Carry-Bits.

LSL R1 ; Logische Schieben unteres Byte


ROL R2 ; Linksrollen des oberen Bytes

Bei der ersten Instruktion gelangt Bit 7 des unteren Bytes in das Carry-Bit, bei der zweiten
Instruktion dann in Bit 0 des oberen Bytes. Nach der zweiten Instruktion hängt Bit 7 des oberen
Bytes im Carry-Bit herum und wir könnten es ins dritte Byte schieben, usw. Natürlich gibt es das
Rollen auch nach rechts, zum Dividieren von 16-Bit-Zahlen gut geeignet. Hier nun alles Rückwärts:

LSR R2 ; Oberes Byte durch 2, Bit 0 ins Carry


ROR R1 ; Carry in unteres Byte und dabei rollen

So einfach ist das mit dem Dividieren bei großen Zahlen. Man sieht sofort, dass Assembler-
Dividieren viel schwieriger zu erlernen ist als Hochsprachen-Dividieren, oder?

Gleich vier mal Spezial-schieben kommt jetzt. Es geht um die Nibble gepackter BCD-Zahlen. Wenn
man nun mal das obere Nibble anstelle des unteren Nibble braucht, dann kommt man um vier mal
Rollen

ROR R1
ROR R1
ROR R1
ROR R1

mit einem einzigen

SWAP R1

herum. Das vertauscht mal eben die oberen vier mit den unteren vier Bits.

Zum Seitenanfang

Addition, Subtraktion und Vergleich

Ungeheuer schwierig in Assembler ist Addieren, Dividieren und Vergleichen. Zart-besaitete


Anfänger sollten sich an dieses Kapitel nicht herantrauen. Wer es trotzdem liest, ist übermütig und
jedenfalls selbst schuld.

Um es gleich ganz schwierig zu machen, addieren wir die 16-Bit-Zahlen in den Registern R1:R2 zu
den Inhalten von R3:R4 (Das ":" heißt nicht Division! Das erste Register gibt das High-Byte, das
zweite nach dem ":" das Low-Byte an).

ADD R2,R4 ; zuerst die beiden Low-Bytes


ADC R1,R3 ; dann die beiden High-Bytes

Anstelle von ADD wird beim zweiten Addieren ADC verwendet. Das addiert auch noch das Carry-Bit
dazu, falls beim ersten Addieren ein Übertrag stattgefunden hat. Sind sie schon dem Herzkasper nahe?

Wenn nicht, dann kommt jetzt das Subtrahieren. Also alles wieder rückwärts und R3:R4 von R1:R2
subtrahiert.

SUB R2,R4 ; Zuerst das Low-Byte


SBC R1,R3 ; dann das High-Byte

Wieder derselbe Trick: Anstelle des SUB das SBC, das zusätzlich zum Register R3 auch gleich noch
das Carry-Bit von R1 abzieht. Kriegen Sie noch Luft? Wenn ja, dann leisten sie sich das folgende:
Abziehen ohne Ernst!

Jetzt kommt es knüppeldick: Ist die Zahl in R1:R2 nun größer als die in R3:R4 oder nicht? Also nicht
SUB, sondern CP, (für ComPare) und nicht SBC, sondern CPC:

CP R2,R4 ; Vergleiche untere Bytes


CPC R1,R3 ; Vergleiche obere Bytes

Wenn jetzt das Carry-Flag gesetzt ist, kann das nur heißen, dass R3:R4 größer ist als R1:R2. Wenn
nicht, dann eben nicht.

Jetzt setzen wir noch einen drauf! Wir vergleichen Register R1 und eine Konstante miteinander: Ist in
Register R16 ein binäres Wechselbad gespeichert?

CPI R16,0xAA

Wenn jetzt das Z-Bit gesetzt ist, dann ist das aber so was von gleich!

Und jetzt kommt die Sockenauszieher-Hammer-Instruktion! Wir vergleichen, ob das Register R1


kleiner oder gleich Null ist.

TST R1

Wenn jetzt das Z-Flag gesetzt ist, ist das Register ziemlich leer und wir können mit BREQ, BRNE,
BRMI, BRPL, BRLO, BRSH, BRGE, BRLT, BRVC oder auch BRVS ziemlich lustig springen.

Sie sind ja immer noch dabei! Assembler ist schwer, gelle? Na dann, kriegen sie noch ein wenig
gepacktes BCD-Rechnen draufgepackt. Beim Addieren von gepackten BCD's kann sowohl die
unterste der beiden Ziffern als auch die oberste überlaufen. Addieren wir im Geiste die BCD-Zahlen
49 (=hex 49) und 99 (=hex 99). Beim Addieren in hex kommt hex E2 heraus und es kommt kein Byte-
Überlauf zustande. Die untersten beiden Ziffern sind beim Addieren übergelaufen (9+9=18 = hex 12).
Folglich ist die oberste Ziffer korrekt um eins erhöht worden, aber die unterste stimmt nicht, sie
müsste 8 statt 2 lauten. Also könnten wir unten 6 addieren, dann stimmt es wieder. Die oberste Ziffer
stimmt überhaupt nicht, weil hex E keine zulässige BCD-Ziffer ist. Sie müsste richtigerweise 4 lauten
(4+9+1=14) und ein Überlauf sollte auftreten. Also, wenn zu E noch 6 addiert werden, kommt
dezimal 20 bzw. hex 14 heraus. Alles ganz easy: Einfach zum Ergebnis noch hex 66 addieren und
schon stimmt alles. Aber gemach! Das wäre nur korrekt, wenn bei der hintersten Ziffer, wie in
unserem Fall, entweder schon beim ersten Addieren oder später beim Addieren der 6 tatsächlich ein
Überlauf in die nächste Ziffer auftrat. Wenn das nicht so ist, dann darf die 6 nicht addiert werden.
Woran ist zu merken, ob dabei ein Übertrag von der unteren in die höhere Ziffer auftrat? Am
Halbübertrags-Bit im Status-Register. Dieses H-Bit zeigt für einige Instruktionen an, ob ein solcher
Übertrag aus dem unteren in das obere Nibble auftrat. Dasselbe gilt analog für das obere Nibble, nur
zeigt hier das Carry-Bit den Überlauf an. Die folgenden Tabellen zeigen die verschiedenen
Möglichkeiten an.
ADD R1,R2 ADD Nibble,6
Korrektur
(Half)Carry-Bit (Half)Carry-Bit
0 0 6 wieder abziehen
1 0 keine
0 1 keine
1 1 (geht gar nicht)
Nehmen wir an, die beiden gepackten BCD-Zahlen seien in R2 und R3 gespeichert, R1 soll den
Überlauf aufnehmen und R16 und R17 stehen zur freien Verfügung. R16 soll zur Addition von 0x66
dienen (das Register R2 kann keine Konstanten addieren), R17 zur Subtraktion der Korrekturen am
Ergebnis. Dann geht das Addieren von R2 und R3 so:

LDI R16,0x66
LDI R17,0x66
ADD R2,R3
BRCC NoCy1
INC R1
ANDI R17,0x0F
NoCy1:
BRHC NoHc1
ANDI R17,0xF0
NoHc1:
ADD R2,R16
BRCC NoCy2
INC R1
ANDI R17,0x0F
NoCy2:
BRHC NoHc2
ANDI R17,0x0F
NoHc2:
SUB R2,R17

Die einzelnen Schritte: Im ersten Schritt werden die beiden Zahlen addiert. Tritt dabei schon ein
Carry auf, dann wird das Ergebnisregister R1 erhöht und eine Korrektur des oberen Nibbles ist nicht
nötig (die obere 6 im Korrekturspeicher R16 wird gelöscht). INC und ANDI beeinflussen das H-Bit
nicht. War nach der ersten Addition das H-Bit schon gesetzt, dann kann auch die Korrektur des
unteren Nibble entfallen (das untere Nibble wird Null gesetzt). Dann wird 0x66 addiert. Tritt dabei
nun ein Carry auf, dann wird wie oben verfahren. Trat dabei ein Half-Carry auf, dann wird ebenfalls
wie oben verfahren. Schließlich wird das Korrektur-Register vom Ergebnis abgezogen und die
Berechnung ist fertig.

Kürzer geht es so.

LDI R16,0x66
ADD R2,R16
ADD R2,R3
BRCC NoCy
INC R1
ANDI R16,0x0F
NoCy:
BRHC NoHc
ANDI R16,0xF0
NoCy:
SUB R2,R16

Ich überlasse es dem Leser zu ergründen, warum das so geht.

Zum Seitenanfang

Umwandlung von Zahlen

Alle Zahlenformate sind natürlich umwandelbar. Die Umwandlung von BCD in ASCII und zurück
war oben schon besprochen (Bitmanipulationen).

Die Umwandlung von gepackten BCD's ist auch nicht schwer. Zuerst ist die gepackte BCD mit
einem SWAP umzuwandeln, so dass das erste Digit ganz rechts liegt. Mit einem ANDI kann dann das
obere (ehemals untere) Nibble gelöscht werden, so dass das obere Digit als reine BCD blank liegt.
Das zweite Digit ist direkt zugänglich, es ist nur das obere Nibble zu löschen. Von einer BCD zu
einer gepackten BCD kommt man, indem man die höherwertige BCD mit SWAP in das obere Nibble
verfrachtet und anschließend die niederwertige BCD damit verODERt.

Etwas schwieriger ist die Umwandlung von BCD-Zahlen in eine Binärzahl. Dazu macht man zuerst
die benötigten Bits im Ergebnisspeicher frei. Man beginnt mit der niedrigstwertigen BCD-Ziffer.
Bevor man diese zum Ergebnis addiert, wird das Ergebnis erstmal mit 10 multipliziert. Dazu
speichert man das Ergebnis irgendwo zwischen, multipliziert es mit 4 (zweimal links schieben/
rotieren), addiert das alte Ergebnis (mal 5) und schiebt noch einmal nach links (mal 10). Jetzt erst
wird die BCD-Ziffer addiert. Tritt bei irgendeinem Schieben oder Addieren des obersten Bytes ein
Carry auf, dann passt die BCD-Zahl nicht in die verfügbaren binären Bytes.

Die Verwandlung einer Binärzahl in BCD-Ziffern ist noch etwas schwieriger. Handelt es sich um 16-
Bit-Zahlen, kann man solange 10.000 subtrahieren, bis ein Überlauf auftritt, das ergibt die erste BCD-
Ziffer. Anschließend subtrahiert man 1.000 bis zum Überlauf und erhält die zweite Ziffer, usw. bis
10. Der Rest ist die letzte Ziffer.Die Ziffern 10.000 bis 10 kann man im Programmspeicher in einer
wortweise organisierten Tabelle verewigen, z.B. so

DezTab:
.DW 10000, 1000, 100, 10

und wortweise mit der LPM-Instruktion aus der Tabelle herauslesen in zwei Register.

Eine Alternative ist eine Tabelle mit der Wertigkeit jedes einzelnen Bits einer 16-Bit-Zahl, also z.B.

.DB 0,3,2,7,6,8
.DB 0,1,6,3,8,4
.DB 0,0,8,1,9,2
.DB 0,0,4,0,9,6
.DB 0,0,2,0,4,8 ; und so weiter bis
.DB 0,0,0,0,0,1

Dann wären die einzelnen Bits der 16-Bit-Zahl nach links herauszuschieben und, wenn es sich um
eine 1 handelt, der entsprechende Tabellenwert per LPM zu lesen und zu den Ergebnisbytes zu
addieren. Ein vergleichsweise aufwendigeres und langsameres Verfahren.

Eine dritte Möglichkeit wäre es, die fünf zu addierenden BCD-Ziffern beginnend mit 00001 durch
Multiplikation mit 2 bei jedem Durchlauf zu erzeugen und mit dem Schieben der umzuwandelnden
Zahl beim untersten Bit zu beginnen.

Es gibt viele Wege nach Rom, und manche sind mühsamer.

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/rechnen.html1/20/2009 7:31:48 PM
Hardware zum Erlernen der Assembler-Programmierung

Pfad: Home => AVR-deutsch => Programmiertechniken => Hardware

Hardware für die AVR-Assembler-Programmierung

Damit es beim Lernen von Assembler nicht zu trocken zugeht, braucht es etwas Hardware zum Ausprobieren. Gerade wenn man die ersten Schritte macht, muss der Lernerfolg schnell sichtbar sein.

Hier werden mit wenigen einfachen Schaltungen im Eigenbau die ersten Hardware-Grundlagen beschrieben. Um es vorweg zu nehmen: es gibt von der Hardware her nichts einfacheres als einen AVR mit den eigenen Ideen zu bestücken. Dafür wird ein Programmiergerät beschrieben, das einfacher und billiger nicht sein kann. Wer dann größeres vorhat,
kann die einfache Schaltung stückweise erweitern.

Wer sich mit Löten nicht herumschlagen will und nicht jeden Euro umdrehen muss, kann ein fertiges Programmierboard erstehen. Die Eigenschaften solcher Boards werden hier ebenfalls beschrieben.

Zum Seitenanfang

Das ISP-Interface der AVR-Prozessoren


Bevor es ins Praktische geht, zunächst ein paar grundlegende Informationen zum Programmieren der Prozessoren. Nein, man braucht keine drei verschiedenen Spannungen, um das Flash-EEPROM eines AVR zu beschreiben und zu lesen. Nein, man braucht keinen weiteren Mikroprozessor, um ein Programmiergerät für einfache Zwecke zu bauen. Nein,
man braucht keine 10 I/O-Ports, um so einem Chip zu sagen, was man von ihm will. Nein, man muss den Chip nicht aus der Schaltung auslöten, in eine andere Fassung stecken, ihn dann dort programmieren und alles wieder rückwärts. Geht alles viel einfacher.

Für all das sorgt ein in allen Chips eingebautes Interface, über das der Inhalt des Flash-Programmspeichers sowie des eingebauten EEPROM's beschrieben und gelesen werden kann. Das Interface arbeitet seriell und braucht genau drei Leitungen:

● SCK: Ein Taktsignal, das die zu schreibenden Bits in ein Schieberegister im AVR eintaktet und zu lesende Bits aus einem weiteren Schieberegister austaktet,
● MOSI: Das Datensignal, das die einzutaktenden Bits vorgibt,
● MISO: Das Datensignal, das die auszutaktenden Bits zum Lesen durch die Programmiersoftware ausgibt.

Damit die drei Pins nicht nur zum Programmieren genutzt werden können, wechseln sie nur dann in den Programmiermodus, wenn das RESET-Signal am AVR (auch: RST oder Restart genannt) auf logisch Null liegt. Ist das nicht der Fall, können die drei Pins als beliebige I/O-Signalleitungen dienen. Wer die drei Pins mit dieser Doppelbedeutung benutzen
möchte und das Programmieren des AVR in der Schaltung selbst vornehmen möchte, muss z.B. einen Multiplexer verwenden oder Schaltung und Programmieranschluss durch Widerstände voneinander entkoppeln. Was nötig ist, richtet sich nach dem, was die wilden Programmierimpulse mit dem Rest der Schaltung anstellen können.

Nicht notwendig, aber bequem ist es, die Versorgungsspannung von Schaltung und Programmier-Interface gemeinsam zu beziehen und dafür zwei weitere Leitungen vorzusehen. GND versteht sich von selbst, VTG bedeutet Voltage Target und ist die Betriebsspannung des Zielsystems. Damit wären wir bei der 6-Draht-ISP-
Programmierleitung. Die ISP6-Verbinder haben die nebenstehende, von ATMEL standardisierte Pinbelegung.

Und wie das so ist mit Standards: immer gab es schon welche, die früher da waren, die alle verwenden und an die sich immer noch (fast) alle halten. Hier ist das der 10-polige Steckverbinder. Er hat noch zusätzlich einen LED-Anschluss, über den die Programmiersoftware mitteilen kann, dass sie fertig mit dem Programmieren ist.
Auch nicht schlecht, mit einer roten LED über einen Widerstand gegen die Versorgungsspannung ein deutliches Zeichen dafür zu setzen, dass die Programmiersoftware ihren Dienst versieht.

Zum Seitenanfang

Programmierer für den PC-Parallel-Port


So, Lötkolben anwerfen und ein Programmiergerät bauen. Es ist denkbar einfach und dürfte mit Standardteilen aus der gut sortierten Bastelkiste schnell aufgebaut sein.

Ja, das ist alles, was es zum Programmieren braucht. Den 25-poligen Stecker steckt man in den Parallelport des PC's, den 10-poligen ISP-Stecker an die AVR-Experimentierschaltung. Wer gerade keinen 74LS245 zur Hand hat, kann auch einen 74HC245
verwenden. Allerdings sollten dann die unbenutzten Eingänge an Pin 11, 12 und 13 einem definierten Pegel zugeführt werden, damit sie nicht herumklappern, unnütz Strom verbraten und HF erzeugen.

Den Rest erledigt die alte ISP-Software, die es auf der ATMEL-Seite kostenlos gibt, PonyProg2000 oder andere Brenn-Software. Allerdings ist bei der Brennsoftware auf die Unterstützung neuerer AVR-Typen zu achten.

Wer eine serielle Schnittstelle hat (oder einen USB-Seriell-Wandler) kann sich zum Programmieren aus dem Studio oder anderer Brenner-Software auch den kleinen, süßen AVR910-Programmer bauen (Bauanleitung und Schaltbild siehe die Webseite von Klaus Leidinger).

Zum Seitenanfang

Experimentalschaltung mit ATtiny13


Dies ist ein sehr kleines Experimentierboard, das Tests mit den vielseitigen Innereien des ATtiny13 ermöglicht.

Bild zeigt

● das ISP10-Programmier-Interface auf der linken Seite, mit einer Programmier-LED, die über einen
Widerstand von 390 Ω an die Betriebsspannung angeschlossen ist,
● den ATtiny13, dessen Reset-Eingang an Pin 1 mit einem Widerstand von 10 kΩ an die Betriebsspannung

führt,
● den Stromversorgungsteil mit einem Brückengleichrichter, der mit 9..15 V aus einem ungeregelten

Netzteil oder einem Trafo gespeist werden kann, und einem kleinen 5 V-Spannungsregler.

Der ATtiny13 braucht keinen externen Quarz oder Taktgenerator, weil er einen internen 9,6 MHz-RC-
Oszillator hat und von der Werksausstattung her mit einem Vorteiler von 8 bei 1,2 MHz arbeitet. Die
Hardware kann auf einem kleinen Experimentierboard aufgebaut werden, wie auf dem Bild zu sehen.

Alle Pins des ATtiny13 sind hier über Lötnägel zugänglich und können mit einfachen Steckverbindern mit
externer Hardware verbunden werden (im Bild eine LED mit Vorwiderstand).

Experimentalschaltung mit AT90S2313


Damit es was mehr zum Programmieren gibt, hier eine einfache Schaltung mit einem schon etwas größeren AVR-Typ. Verwendbar ist der veraltete AT90S2313 oder sein neuerer Ersatztyp ATtiny2313. Die Schaltung hat

● ein kleines geregeltes Netzteil für den Trafoanschluss (für künftige Experimente mit einem 1A-Regler ausgestattet),
● einen Quarz-Taktgenerator (hier mit einem 10 MHz-Quarz, es gehen aber auch langsamere),
● die Teile für einen sicheren Reset beim Einschalten,
● das ISP-Programmier-Interface (hier mit einem ISP10PIN-Anschluss).

Damit kann man im Prinzip loslegen und an die vielen freien I/O-Pins des 2313 jede Menge Peripherie dranstricken.

Das einfachste Ausgabegerät dürfte für den Anfang eine LED sein, die über einen Widerstand gegen die Versorgungsspannung geschaltet wird und die man an einem Portbit zum Blinken animieren kann.

Zum Seitenanfang

Fertige Programmierboards für die AVR-Familie


Wer nicht selber löten will oder gerade einige Euros übrig hat und nicht weiss, was er damit anstellen soll, kauft sich ein fertiges Programmierboard.

ATMEL STK500

Leicht erhältlich ist das STK500 von ATMEL. Es bietet u.a.:

● Sockel für die Programmierung der meisten AVR-Typen,


● serielle und parallele Low- und High-Voltage-Programmierung,
● ISP6PIN- und ISP10PIN-Anschluss für externe Programmierung,
● programmierbare Oszillatorfrequenz und Versorgungsspannungen,
● steckbare Tasten und LEDs,
● einen steckbaren RS232C-Anschluss (UART),
● ein serielles Flash-EEPROM,
● Zugang zu allen Ports über 10-polige Pfostenstecker.

Die Experimente können mit dem mitgelieferten AT90S8515 oder ATmega8515 sofort beginnen. Das Board wird über eine serielle Schnittstelle (COMx) an den Rechner gekoppelt und von den neueren Versionen des Studio's von ATMEL bedient. Für die Programmierung externer Schaltungen besitzt das Board einen ISP6-Anschluss. Damit dürften alle
Hardware-Bedürfnisse für den Anfang abgedeckt sein.

Für den Anschluss an eine USB-Schnittstelle am PC braucht man noch einen handelsüblichen USB-Seriell-Wandler. Für eine gute automatische Erkennung durch das Studio ist im Gerätemanager eine der Schnittstellen COM2 bis COM4 für den Wandler und eine Geschwindigkeit von 115 kBaud einzustellen.

Damit dürften alle Hardware-Bedürfnisse für den Anfang abgedeckt sein.

AVR Dragon

Wer an seinem PC oder Notebook keine RS232-Schnittstelle mehr hat, ist mit dem preiswerten AVR Dragon gut bedient. An das kleine schmucke Board kann man eine ISP6- oder ISP10-Schnittstelle anbringen und damit externe Hardware programmieren. Das Board hat auch Schnittstellen für die Hochspannungsprogrammierung.

Andere Boards

Es gibt eine Vielzahl an Boards. Eine Einführung in alle verfügbare Boards kann hier nicht gegeben werden.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/hardware.html1/20/2009 7:32:00 PM
Warum Assembler lernen?

Pfad: Home => AVR-Überblick => Programmiertechniken => Warum Assembler?

Programmiertechnik für Anfänger in AVR


Assemblersprache
Assembler oder Hochsprache, das ist hier die Frage. Warum soll man noch eine neue Sprache lernen,
wenn man schon welche kann? Das beste Argument: Wer in Frankreich lebt und nur Englisch kann,
kann sich zwar durchschlagen, aber so richtig heimisch und unkompliziert ist das Leben dann nicht.
Mit verquasten Sprachkonstruktionen kann man sich zwar durchschlagen, aber elegant hört sich das
meistens nicht an. Und wenn es schnell gehen muss, geht es eben öfter schief.

In der Kürze liegt die Würze


Assemblerbefehle übersetzen sich 1 zu 1 in Maschinenbefehle. Auf diese Weise macht der Prozessor
wirklich nur das, was für den angepeilten Zweck tatsächlich erforderlich ist und was der
Programmierer auch gerade will. Keine extra Schleifen und nicht benötigten Features stören und
blasen den ausgeführten Code auf. Wenn es bei begrenztem Programmspeicher und komplexerem
Programm auf jedes Byte ankommt, dann ist Assembler sowieso Pflicht. Kürzere Programme lassen
sich wegen schlankerem Maschinencode leichter entwanzen, weil jeder einzelne Schritt Sinn macht
und zu Aufmerksamkeit zwingt.

zum Seitenanfang

Schnell wie Hund


Da kein unnötiger Code ausgeführt wird, sind Assembler-Programme maximal schnell. Jeder Schritt
ist von voraussehbarer Dauer. Bei zeitkritischen Anwendungen, wie z.B. bei Zeitmessungen ohne
Hardware-Timer, die bis an die Grenzen der Leistungsfähigkeit des Prozessors gehen sollen, ist
Assembler ebenfalls zwingend. Soll es gemütlich zugehen, können Sie programmieren wie Sie
wollen.

Assembler ist leicht erlernbar


Es stimmt nicht, dass Assembler komplizierter und schwerer erlernbar ist als Hochsprachen. Das
Erlernen einer einzigen Assemblersprache macht Sie mit den wichtigsten Grundkonzepten vertraut,
das Erlernen von anderen Assembler-Dialekten ist dann ein Leichtes. Der erste Code sieht nicht sehr
elegant aus, mit jedem Hunderter an Quellcode sieht das schon schöner aus. Schönheitspreise kriegt
man erst ab einigen Tausend Zeilen Quellcode. Da viele Features prozessorabhängig sind, ist
Optimierung eine reine Übungsangelegenheit und nur von der Vertrautheit mit der Hardware und
dem Dialekt abhängig. Die ersten Schritte fallen in jeder neu erlernten Sprache nicht leicht und nach
wenigen Wochen lächelt man über die Holprigkeit und Umständlichkeit seiner ersten Gehversuche.
Manche Assembler-Befehle lernt man eben erst nach Monaten richtig nutzen.

zum Seitenanfang

AVR sind ideal zum Lernen


Assemblerprogramme sind gnadenlos, weil sie davon ausgehen, dass der Programmierer jeden Schritt
mit Absicht so und nicht anders macht. Alle Schutzmechanismen muss man sich selber ausdenken
und auch programmieren, die Maschine macht bedenkenlos jeden Unsinn mit. Kein Fensterchen
warnt vor ominösen Schutzverletzungen, es sei denn man hat das Fenster selber programmiert.
Denkfehler beim Konstruieren sind aber genauso schwer aufzudecken wie bei Hochsprachen. Das
Ausprobieren ist bei den ATMEL-AVR aber sehr leicht, da der Code rasch um einige wenige
Diagnostikzeilen ergänzt und mal eben in den Chip programmiert werden kann. Vorbei die Zeiten mit
EPROM löschen, programmieren, einsetzen, versagen und wieder von vorne nachdenken.
Änderungen sind schnell gemacht, kompiliert und entweder im Studio simuliert, auf dem STK-Board
ausprobiert oder in der realen Schaltung einprogrammiert, ohne dass sich ein IC-Fuß verbogen oder
die UV-Lampe gerade im letzten Moment vor der großen Erleuchtung den Geist aufgegeben hat.

zum Seitenanfang

Ausprobieren
Nur Mut bei den ersten Schritten. Wenn Sie schon eine Programmiersprache können, vergessen Sie
sie erst mal gründlich, weil sonst die allerersten Schritte schwerfallen. Hinter jeder Assemblersprache
steckt auch ein Prozessorkonzept, und große Teile der erlernten Hochsprachenkonzepte machen in
Assembler sowieso keinen Sinn. Die ersten fünf Befehle gehen schwer, dann geht es exponentiell
leichter. Nach den ersten 10 Zeilen nehmen Sie den ausgedruckten Instruction Set Summary mal für
eine Stunde mit in die Badewanne und wundern sich ein wenig, was es so alles zu Programmieren
und zum Merken gibt. Versuchen Sie zu Anfang keine Mega-Maschine zu programmieren, das geht
in jeder Sprache gründlich schief. Heben Sie erfolgreich programmierte Codezeilen gut dokumentiert
auf, Sie brauchen sie sowieso bald wieder.

Viel Lernerfolg.

zum Seitenanfang

©2002-2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/Warum.html1/20/2009 7:32:01 PM
Werkzeuge der Assembler-Programmierung

Pfad: Home => AVR-deutsch => Programmiertechniken => Werkzeuge

Werkzeuge für die AVR-Assembler-Programmierung


In diesem Abschnitt werden die Werkzeuge vorgestellt, die zum Assembler-Programmieren nötig sind. Dabei werden zunächst Werkzeuge besprochen, die jeden Arbeitsschritt separat
erledigen, damit die zugrunde liegenden Schritte einzeln nachvollzogen werden können. Erst danach wird eine integrierte Werkzeugumgebung vorgestellt.

Für die Programmierung werden vier Teilschritte und Werkzeuge benötigt. Im einzelnen handelt es sich um

1. den Editor,
2. den Assembler,
3. das Programmier-Interface, und
4. den Simulator.

Die dargestellten Fenster sind alle © ATMEL. Es wird darauf hingewiesen, dass die Bilder mit Software erstellt wurden, die heute nicht mehr verfügbar und sinnvoll anwendbar ist. Sie wird
hier nur verwendet, um die Teilschritte klarzumachen.

Der Editor
Assemblerprogramme schreibt man mit einem Editor. Der braucht im Prinzip nicht mehr können als ASCII-Zeichen zu schreiben und zu speichern. Im Prinzip täte es ein sehr einfaches
Schreibgerät. Wir zeigen hier ein etwas veraltetes Gerät, den WAVRASM von ATMEL.

Der WAVRASM sieht nach der Installation und nach


dem Start eines neuen Projektes etwa so aus:

Im Editor schreiben wir einfach die Assemblerbefehle und Befehlszeilen


drauf los, gespickt mit Kommentaren, die alle mit einem Semikolon
beginnen. Das sollte dann etwa so aussehen:

Nun wird das Assembler-Programm mit dem File-Menue in irgendein Verzeichnis, am besten in ein eigens dazu errichtetes, abgespeichert. Fertig ist der Assembler-Quellcode.

Manche Editoren erkennen Instruktionen und Symbole und


färben diese Worte entsprechend ein, so dass man Tippfehler
schnell erkennt und ausbessern kann (Syntax-Highlighting
genannt). In einem solchen Editor sieht unser Programm so aus:

Auch wenn die im Editor eingegebenen Worte noch ein wenig kryptisch aussehen, sie sind von Menschen lesbar und für den Mikroprozessor noch völlig unbrauchbar.

Zum Seitenanfang

Der Assembler
Nun muss das ganze Programm von der Textform in die Maschinen-sprachliche Form gebracht werden. Den Vorgang heisst man Assemblieren, was in etwa "Zusammenbauen", "Auftürmen"
oder auch "zusammenschrauben" bedeutet. Das erledigt ein Programm, das auch so heißt: Assembler. Derer gibt es sehr viele. Für AVR heißen die zum Beispiel "AvrAssembler" oder
"AvrAssembler2" (von ATMEL, Bestandteil der Studio-Entwicklungsumgebung), "TAvrAsm" (Tom's AVR Assembler) oder mein eigener "GAvrAsm" (Gerd's AVR Assembler). Welchen man
nimmt, ist weitgehend egal, jeder hat da so seine Stärken, Schwächen und Besonderheiten.

Beim WAVRASM klickt man dazu einfach auf den Menuepunkt mit der
Aufschrift "Assemble". Das Ergebnis ist in diesem Bild zu sehen. Der
Assembler geruht uns damit mitzuteilen, dass er das Programm übersetzt
hat. Andernfalls würfe er mit dem Schlagwort Error um sich. Immerhin
ein Wort Code ist dabei erzeugt worden. Und er hat aus unserer einfachen
Textdatei gleich vier neue Dateien erzeugt. In der ersten der vier neuen
Dateien, TEST.EEP, befindet sich der Inhalt, der in das EEPROM
geschrieben werden soll. Er ist hier ziemlich uninteressant, weil wir
nichts ins EEPROM programmieren wollten. Hat er gemerkt und die
Datei auch gleich wieder gelöscht.

Die zweite Datei, TEST.HEX, ist schon wichtiger, weil hier die Befehlsworte untergebracht sind. Diese Datei brauchen wir zum
Programmieren des Prozessors. Sie enthält die nebenstehenden Hieroglyphen. Die hexadezimalen Zahlen sind als ASCII-Zeichen
aufgelöst und werden mit Adressangaben und Prüfsummen zusammen abgelegt. Dieses Format heisst Intel-Hex-Format und ist
uralt. Jedenfalls versteht diesen Salat jede Programmier-Software recht gut.

Die dritte Datei, TEST.OBJ, kriegen wir später, sie wird zum Simulieren
gebraucht. Ihr Format ist hexadezimal und von ATMEL speziell zu diesem
Zweck definiert. Sie sieht im Hex-Editor wie abgebildet aus. Merke: Diese
Datei wird vom Programmiergerät nicht verstanden!

Die vierte Datei, TEST.LST, können wir uns mit einem Editor anschauen. Sie enthält das Nebenstehende. Wir
sehen das Programm mit allen Adressen (hier: "000000"), Maschinenbefehlen (hier: "cfff") und
Fehlermeldungen (hier: keine) des Assemblers. Die List-Datei braucht man selten, aber gelegentlich.

Zum Seitenanfang

Das Programmieren des Chips


Nun muss der in der Hex-Datei abgelegte Inhalt dem AVR-Chip beigebracht werden. Das erledigt Brenner-Software. Üblich sind die Brenn-Tools im Studio von ATMEL, das vielseitige Pony-
Prog 2000 und andere mehr (konsultiere die Lieblings-Suchmaschine).

Das Brennen wird hier am Beispiel des ISP gezeigt. Das


gibt es nicht mehr, arbeitet aber sehr viel anschaulicher als
moderne Software, weil es einen Blick in das Flash-
Memory des AVR ermöglicht. Wir starten das Programm
ISP, erzeugen ein neues Projekt und laden die gerade
erzeugte Hex-Datei mit LOAD PROGRAM. Das sieht dann
wie im Bild aus. Wenn wir nun mit dem Menue Program
den Chip programmieren, dann legt dieser gleich los. Beim
Brennen gibt eine Reihe von weiteren Voraussetzungen
(richtige Schnittstelle auswählen, Adapter an Schnittstelle
angeschlossen, Chip auf dem Programmierboard
vorhanden, Stromversorgung auf dem Board
eingeschaltet, ...), ohne die das natürlich nicht geht.

Zum Seitenanfang

Das Simulieren im Studio


In einigen Fällen hat selbst geschriebener Code nicht bloß Tippfehler, sondern hartnäckige logische Fehler. Die Software macht einfach nicht das, was sie soll, wenn der Chip damit gebrannt
wird. Tests auf dem Chip selbst können kompliziert sein, speziell wenn die Hardware aus einem Minimum besteht und keine Möglichkeit besteht, Zwischenergebnisse auszugeben oder
wenigstens Hardware-Signale zur Fehlersuche zu benutzen. In diesen Fällen hat das Studio-Software-Paket von ATMEL einen Simulator, der für die Entwanzung ideale Möglichkeiten bietet.
Das Programm kann Schritt für Schritt abgearbeitet werden, die Zwischenergebnisse in Prozessorregistern sind überwachbar, etc.

Die folgenden Bilder sind der Version 4 entnommen, die ältere Version 3 sieht anders aus, macht aber in etwa dasselbe. Die Studio Software enthält alles, was man zur Entwicklung, zur
Fehlersuche, zur Simulation, zum Brennen der Programme und an Hilfen braucht. Nach der Installation und dem Start des Riesenpakets (z. Zt. ca. 100 MB) sieht das erste Bild wie folgt aus:

Der erste Dialog fragt, ob wir


ein neues oder bereits
bestehendes Projekt öffnen
wollen. Im Falle einer
Erstinstallation ist "New
Project" die korrekte
Antwort. Der Knopf
"Next>>" bringt uns zum
Einstellungsdialog für das
neue Projekt:

Hier wird die Plattform "Simulator" ausgewählt.

Ferner wird hier der Prozessor-Zieltyp (hier: ATmega8) ausgewählt und der
Dialog mit "Finish" abgeschlossen. Das öffnet ein ziemlich großes Fenster mit
ziemlich vielen Bestandteilen:

● links oben das Fenster mit der Projektverwaltung, in dem Ein- und Ausgabedateien verwaltet werden können,
● in der Mitte oben ist das Editorfenster zu sehen, das den Inhalt der Datei "test1.asm" anzeigt und in das der Quelltext eingegeben werden kann,
● rechts oben die Hardware-Ansicht des Zielprozessors (dazu später mehr),
● links unten das "Build"-Fensters, in dem Diagnose-Ausgaben erscheinen, und
● rechts unten ein weiteres Feld, in dem diverse Werte beim Entwanzen angezeigt werden.

Alle Fenster sind in Größe und Lage verschiebbar.

Für den Nachvollzug der nächsten Schritte im Studio ist es notwendig, das im Editorfenster sichtbare Programm abzutippen (zu den Bestandteilen des Programmes später mehr) und mit "Build"
und "Build" zu übersetzen. Das bringt die Ausgabe im unteren Build-Fenster zu folgender Ausgabe:

Fenster teilt uns mit, dass das Programm fehlerfrei übersetzt wurde und wieviel Code dabei erzeugt wurde (14 Worte, 0,2% des verfügbaren Speicherraums.

Nun wechseln wir in das Menü "Debug", was unsere Fensterlandschaft ein wenig verändert:

Im linken Editor-Fenster taucht nun ein gelber Pfeil auf, der auf die erste ausführbare
Instruktion des Programmes zeigt. Mit "View", "Toolbars" und "Processor" bringt man das
Prozessorfenster rechts zur Anzeige. Es bringt uns Informationen über die aktuelle
Ausführungsadresse, die Anzahl der verarbeiteten Instruktionen, die verstrichene Zeit und nach
dem Klicken auf das kleine "+" neben "Registers" den Inhalt der Register.

Mit "Debug" und "Step into" oder der Taste F11 wird nun ein Einzelschritt vorgenommen.

Der Programmzähler hat sich nun verändert, er steht auf "0x000001". Der
Schrittzähler hat einen Zyklus gezählt und im Register R16 steht nun hexadezimal
"0xFF" oder dezimal 255. LDI lädt also einen Hexadezimalwert in ein Register.

Nach einem weiteren Schritt mit F11 und Aufklappen von PORTB im Hardware-
Fenster "I/O-View" ist die Wirkung der gerade abgearbeiteten Instruktion
"out PORTB,rmp" zu sehen:

Das Richtungs-Port-Register
Data Direction PortB (DDRB)
hat nun 0xFF und in der
Bitanzeige unten acht
schwarze Kästchen.

Mit zwei weiteren


Einzelschritten (F11) hat dann
der Ausgabeport PORTB den
Hexadezimalwert "0x55".

Zwei weitere Schritte klappen die vier schwarzen und die vier weißen
Kästchen um.

Erstaunlicherweise ist nun der Port PINB dem vorhergehenden Bitmuster gefolgt.

Aber dazu dann später im Abschnitt über Ports.

Soweit dieser kleine Ausflug in die Welt des Simulators. Er kann noch viel mehr, deshalb sollte dieses Werkzeug oft und insbesondere bei allen hartnäckigen Fällen von Fehlern verwendet
werden. Klicken Sie sich mal durch seine Menues, es gibt viel zu entdecken.

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/werkzeuge.html1/20/2009 7:32:45 PM
Werkzeuge der Assembler-Programmierung: Studio

Pfad: Home => AVR-deutsch => Programmiertechniken => Studio 4

Erste Schritte mit dem Studio 4


In diesem Abschnitt werden die ersten Schritte vorgestellt, die zum Assembler-Programmieren und
dem Simulieren mit dem ATMEL-Studio 4 nötig sind. Das Studio gibt es als freie Software auf der
Webseite von ATMEL zum Download. Die dargestellten Fenster sind alle © ATMEL. Es wird darauf
hingewiesen, dass es unterschiedliche Versionen der Studios mit unterschiedlichem Aussehen und
unterschiedlicher Bedienung gibt. Diese Darstellung ist kein Handbuch, sie soll lediglich mit einigen
wenigen Möglichkeiten vertraut machen, die Anfängern helfen können, die ersten Schritte zu
machen. Die Installation wird hier nicht beschrieben.

Zum Seitenanfang

Neues Projekt beginnen


Nach dem Starten von Studio 4 und dem Anlegen eines neuen Projektes sollte sich etwa folgendes
Bild zeigen.

Nach der Eingabe des Projektnamens und der Auswahl eines Ordners zum Speichern der
Projektdateien werden wir zur Auswahl eines AVR-Typs genötigt:

In dem eingebauten Editor öffnet sich gleich eine Textdatei, in der das Assembler-Programm, der
Quellcode, eingetippt werden kann.

Das war es denn auch schon mit dem Editor.

Zum Seitenanfang

Simulator ist reine Ansichtssache


Um dieses Programm im Simulator zu testen, wird im Menu Build-And-Run gewählt. Im unteren
Fenster, das Output-Window heißt, wird die Ausgabe des Assemblers angezeigt. Der Simulator zeigt
dann mit einem gelben Pfeil an der entsprechenden Zeile an, welchen Befehl des Programmes er als
nächstes auszuführen gedenkt. Damit wir sehen, was passiert, öffnen wir im linken Fenster einen
Blick auf die Register R16..R31.

Mit View können wir beim Simulieren auch noch weitere Anzeigearten anstelle des Output-Fensters
aktivieren, z.B. die Register. Mit F11 geht es zeilenweise im Einzelschritt durch die Simulation. Nach
zwei Einzelschritten sieht das im Register-Fenster so aus:

Nach der Durchführung der EOR-Instruktion hat sich der Registerinhalt von R17 geändert, im
Registerfenster erscheint der Wert nun in rot.

Die Flags aus dem Statusregister SREG können im linken Fenster unter I/O, CPU und SREG
während der Simulation überwacht werden.

Das gleiche Fenster zeigt auch die Inhalte von Ports an, hier der Port B.

Zum Seitenanfang

Programmieren des AVRs


Um das fertige Programm in den AVR zu übertragen, kann man im Studio 4 das eingebaute Interface
zum Programmierboard STK500 einsetzen. Das findet sich unter Tools und kommuniziert dann mit
dem Studio.

Damit kann man das eben im Studio gerade editierte, assemblierte und simulierte Programm oder
auch ein extern assembliertes Programm als .hex-Datei in den gewählten AVR übertragen.

Verfügt man nicht über ein STK500 oder ein anderes, vom Studio unterstütztes Programmiergerät,
dann kann man die vom Studio erzeugte .hex- und .eep-Dateien natürlich auch mittels eines externen
Programmes in den AVR übertragen.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/studio4.html1/20/2009 7:32:47 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_1.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_1.gif1/20/2009 7:32:52 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_2.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_2.gif1/20/2009 7:32:55 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_3.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_3.gif1/20/2009 7:32:59 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_4.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_4.gif1/20/2009 7:33:06 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_5.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_5.gif1/20/2009 7:33:12 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_6.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_6.gif1/20/2009 7:33:15 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_7.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_7.gif1/20/2009 7:33:20 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_8.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_8.gif1/20/2009 7:33:27 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_9.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_9.gif1/20/2009 7:33:28 PM
http://www.avr-asm-tutorial.net/avr_gra/st4_10.gif

http://www.avr-asm-tutorial.net/avr_gra/st4_10.gif1/20/2009 7:33:30 PM
Werkzeuge der Assembler-Programmierung

Pfad: Home => AVR-deutsch => Programmiertechniken => Struktur

Struktur von AVR-Assembler-Programmen


In diesem Abschnitt werden die Strukturen vorgestellt, die für Assembler-Programme typisch sind
und sich immer wieder wiederholen. Dazu gehören Kommentare, die Angaben im Kopf des
Programmes, der Code zu Beginn des eigentlichen Programmes und der Aufbau von Programmen.

Kommentare
Das wichtigste an Assemblerprogrammen sind die Kommentare. Ohne Kommentierung des
geschriebenen Codes blickt man schon nach wenigen Tagen oft nicht mehr durch, wofür das
Programm gut war oder was an dieser Stelle des Programmes eigentlich warum getan wird. Man
kann natürlich auch ohne Kommentare Programme schreiben, vor allem wenn man sie vor anderen
und vor sich geheim halten will.

Ein Kommentar beginnt mit einem Semikolon. Alles, was danach in dieser Zeile folgt, wird vom
Übersetzungsprogramm, dem Assembler, einfach ignoriert. Wenn man mehrere Zeilen lange
Kommentare schreiben möchte, muss man eben jede weitere Zeile mit einem Semikolon beginnen.
So sieht dann z.B. der Anfang eines Assemblerprogrammes z.B. so aus:

;
; Klick.asm, Programm zum Ein- und Ausschalten eines Relais alle
zwei Sekunden
; Geschrieben von G.Schmidt, letzte Änderung am 6.10.2001
;

Kommentieren kann und soll man aber auch einzelne Abschnitte eines Programmes, wie z.B. eine
abgeschlossene Routine oder eine Tabelle. Randbedingungen wie z.B. die dabei verwendeten
Register, ihre erwarteten Inhalte oder das Ergebnis nach der Bearbeitung des Teilabschnittes
erleichtern das spätere Aufsuchen von Fehlern und vereinfachen nachträgliche Änderungen.

Man kann aber auch einzelne Zeilen mit Befehlen kommentieren, indem man den Rest der Zeile mit
einem Semikolon vor dem Assembler abschirmt und dahinter alles mögliche anmerkt:

LDI R16,0x0A ; Hier wird was geladen


MOV R17,R16 ; und woanders hinkopiert

Zum Seitenanfang

Angaben im Kopf des Programmes


Den Sinn und Zweck des Programmes, sein Autor, der Revisionsstand und andere Kommentare
haben wir schon als Bestandteil des Kopfes identifiziert. Weitere Angaben, die hier hin gehören, sind
der Prozessortyp, für den die Software geschrieben ist, die wichtigsten Konstanten (zur
übersichtlichen Änderung) und die Festlegung von errinnerungsfördernden Registernamen.

Der Prozessortyp hat dabei eine besondere Bedeutung. Programme laufen nicht ohne Änderungen auf
jedem Prozessortyp. Nicht alle Prozessoren haben den gleichen Befehlssatz, jeder Typ hat seine
typische Menge an EEPROM und SRAM, usw. Alle diese Besonderheiten werden in einer
besonderen Kopfdatei (header file) festgelegt, die in den Code importiert wird. Diese Dateien heissen
je nach Typ z.B. 2323def.inc, 8515def.inc, etc. und werden vom Hersteller zur Verfügung gestellt. Es
ist guter Stil, mit dieser Datei sofort nach dem Kommentar im Kopf zu beginnen. Sie wird
folgendermaßen eingelesen:

.NOLIST ; Damit wird das Auflisten der Datei abgestellt


.INCLUDE "C:\avrtools\appnotes\8515def.inc" ; Import der Datei
.LIST ; Auflisten wieder anschalten

Der Pfad, an dem sich die Header-Datei befindet, kann natürlich weggelassen werden, wenn sie sich
im gleichen Verzeichnis wie die Assemblerdatei befindet. Andernfalls ist der Pfad entsprechend den
eigenen Verhältnissen anzupassen.

Das Auflisten der Datei beim Übersetzen kann nervig sein, weil solche Header-Dateien sehr lang
sind, beim Auflisten des übersetzten Codes (entstehende .lst-Datei) entsprechend lange Listen von
meist uninteressanten (weil trivialen) Informationen produzieren. Das Abschalten vor dem Einlesen
der Header-Datei spart jede Menge Papier beim Ausdrucken der List-Datei.

Es lohnt sich, einen kurzen Blick in die Include-Datei zu werfen. Zu Beginn der Datei wird mit

.DEVICE AT90S8515 ; Festlegung des Zieldevices

der Zielchip definiert. Das wiederum bewirkt, dass Befehle, die auf dem Zielchip nicht definiert sind,
vom Assembler mit einer Fehlermeldung zurückgewiesen werden. Die Device-Anweisung an den
Assembler braucht also beim Einlesen der Header-Datei nicht noch einmal in den Quellcode
eingegeben werden (ergäbe eine Fehlermeldung).

Hier sind z.B. auch die Register XH, XL, YH, YL, ZH und ZL definiert, die beim byteweisen Zugriff
auf die Doppelregister X, Y und Z benötigt werden. Ferner sind darin alle Port-Speicherstellen
definiert, z.B. erfolgt hier die Übersetzung von PORTB in hex 18. Schließlich sind hier auch alle Port-
Bits mit denjenigen Namen registriert, die im Datenblatt des jeweiligen Chips verwendet werden. So
wird hier z.B. das Portbit 3 beim Einlesen von Port B als PINB3 übersetzt, exakt so wie es auch im
Datenblatt heißt.

Mit anderen Worten: vergisst man die Einbindung der Include-Datei des Chips zu Beginn des
Programmes, dann hagelt es Fehlermeldungen, weil der Assembler nur Bahnhof versteht. Die
resultierenden Fehlermeldungen sind nicht immer sehr aussagekräftig, weil fehlende Labels und
Konstanten vom ATMEL-Assembler nicht mit einer Fehlermeldung quittiert werden. Stattdessen
nimmt der Assembler einfach an, die fehlende Konstante sei Null und übersetzt einfach weiter. Man
kann sich leicht vorstellen, welches Chaos dabei herauskommt. Der arglose Programmierer denkt:
alles in Ordnung. In Wirklichkeit wird ein ziemlicher Käse im Chip ausgeführt.

In den Kopf des Programmes gehören insbesondere auch die Register-Definitionen, also z.B.

.DEF mpr = R16 ; Das Register R16 mit einem Namen belegen

Das hat den Vorteil, dass man eine vollständige Liste der Register erhält und sofort sehen kann,
welche Register verwendet werden und welche noch frei sind. Das Umbenennen vermeidet nicht nur
Verwendungskonflikte, die Namen sind auch aussagekräftiger.

Ferner gehört in den Kopf die Definition von Konstanten, die den gesamten Programmablauf
beeinflussen können. So eine Konstante wäre z.B. die Oszillatorfrequenz des Chips, wenn im
Programm später die serielle Schnittstelle verwendet werden soll. Mit

.EQU fq = 4000000 ; Quarzfrequenz festlegen

zu Beginn der Assemblerdatei sieht man sofort, für welchen Takt das Programm geschrieben ist.
Beim Umschreiben auf eine andere Frequenz muss nur diese Zahl geändert werden und man braucht
nicht den gesamten Quelltext nach dem Auftauchen von 4000000 zu durchsuchen.

Zum Seitenanfang

Angaben zum Programmbeginn


Nach dem Kopf sollte der Programmcode beginnen. Am Beginn jedes Codes stehen die Reset- und
Interrupt-Vektoren (zur Funktion siehe Sprung). Da diese relative Sprünge enthalten müssen, folgen
darauf am besten die Interrupt-Service-Routinen. Danach ist ein guter Platz für abgeschlossene
Unterprogramme. Danach sollte das Hauptprogramm stehen.

Das Hauptprogramm beginnt mit immer mit dem Einstellen der Register-Startwerte, dem
Initialisieren des Stackpointers und der verwendeten Hardware. Danach geht es programmspezifisch
weiter.

Zum Seitenanfang

Strukturierung von Programmen


Der beschriebene Standardaufbau ist in der Vorlage enthalten, die auch als .asm-Version im
Quellverzeichnis vorliegt.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/struktur.html1/20/2009 7:33:32 PM
Standard sheet for 8515 assembler

Pfad: Home => AVR-main => beginners => Standard 8515 file

Standard 8515 programming file structure


; ***************************************************************
; * *
; * *
; * *
; * *
; * *
; * (C)2002 by Letzte Änderung: *
; ***************************************************************
;
; Hardware Anforderungen:
;
; Software Funktionen:
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Konstanten
;
.EQU xyz = 12345
;
; Benutzte Register
;
.DEF mpr = R16
;
; Code beginnt hier
;
.CSEG
.ORG $0000
;
; Reset- und Interrupt-Vektoren
;
rjmp Start ; Reset-vector
rjmp IInt0 ; External Interrupt Request 0
rjmp IInt1 ; External Interrupt Request 1
rjmp TCpt1 ; Timer/Counter1 Capture event
rjmp TCmpA ; Timer/Counter1 Compare match A
rjmp TCmpB ; Timer/Counter1 Compare Match B
rjmp TOvf1 ; Timer/Counter1 Overflow
rjmp TOvf0 ; Timer/Counter0 Overflow
rjmp SIStc ; SPI Serial Transfer complete
rjmp URxAv ; Uart Rx char available
rjmp UTxDe ; Uart Tx data register empty
rjmp UTxCp ; Uart Tx complete
rjmp AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0
;
IInt0:
reti
;
; External Interrupt 1
;
IInt1:
reti
;
; Timer/Counter 1, Capture event
;
TCpt1:
reti
;
; Timer/Counter 1, Compare match interrupt A
;
TCmpA:
reti
;
; Timer/Counter 1, Compare Match interrupt B
;
TCmpB:
reti
;
; Timer/Counter 1, Overflow interrupt
;
TOvf1:
reti
;
; Timer/Counter 0, Overflow interrupt
;
TOvf0:
reti
;
; SPI Serial Transfer Complete
;
SIStc:
reti
;
; Uart Rx Complete Interrupt
;
URxAv:
reti
;
; Uart Data register empty interrupt
;
UTxDe:
reti
;
; Uart Tx complete interrupt
;
UTxCp:
reti
;
; Analog comparator interrupt
;
AnaCp:
reti
;
; **************** Ende der Interrupt Service Routinen *********
;
; Verschiedene Unterprogramme
;
; **************** Ende der Unterprogramme *********************
;
; ******************** Hauptprogram ****************************
;
; Hauptprogramm beginnt hier
;
Start:
rjmp start

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/8515std.html1/20/2009 7:33:33 PM
Werkzeuge der Assembler-Programmierung: Studio

Pfad: Home => AVR-deutsch => Programmiertechniken => Werkzeuge

Werkzeuge für die AVR-Assembler-


Programmierung
In diesem Abschnitt werden die ersten Schritte vorgestellt, die zum Assembler-Programmieren mit
dem Board STK500 mittels ATMEL-Studio 3 (Version 3.52) nötig sind. Beschrieben wird

1. das Editieren,
2. das Assemblieren, und
3. der Simulator.

Die nötigen Software-Werkzeuge gibt es bei auf der Webseite von ATMEL, die auch das Copyright
für diese freie Software besitzen. Die dargestellten Fenster sind alle © ATMEL. Es wird darauf
hingewiesen, dass es unterschiedliche Versionen der Software mit unterschiedlichem Aussehen und
unterschiedlicher Bedienung gibt. Diese Darstellung ist kein Handbuch, sie soll lediglich mit einigen
wenigen Möglichkeiten vertraut machen, die Anfängern helfen können, die ersten Schritte zu
machen. Die Installation wird hier nicht beschrieben. Nach dem Starten von Studio 3 sollte sich etwa
folgendes Bild zeigen.

Zum Seitenanfang

Der Editor
Ein Assembler-Programm ist eine einfache Textdatei. Damit mit der Datei auch alle anderen
Einstellungen zu diesem Programm gleichzeitig verwaltet werden können, ist das gesamte
Softwareprojekt im Studio 3 als Projekt verwaltet. Als erstes ist daher ein neues Projekt anzulegen.
Das geht mit Project-New. Hier geben wir den Projektnamen, den Ordner und den gewünschten
Assembler an.

Das öffnet nun die Projektübersicht.

Mit rechtem Mausklick auf Assembler Files und Create New File eröffnen wir eine Textdatei, die das
Assemblerprogramm aufnehmen kann.

In das Editorfenster geben wir nun unser Programm ein. Hier ist eines, das wechselnd die Lampen an
Port B an und aus macht.

Man beachte, dass der Simulator die eingegebenen Befehlsworte für den Prozessor nur dann erkennt
und blau einfärbt, wenn sie in Kleinbuchstaben geschrieben sind! Labels und Defs werden nach wie
vor nicht erkannt. Man beachte ferner, dass das Verzeichnis, in dem sich die Include-Dateien
befinden, mit den neueren Studio-Versionen geändert hat.

Assemblieren der Quelldateien


Nach der Eingabe des Programmes im Editor wird assembliert. In der Projektansicht reicht ein Klick
mit der rechten Maustaste und die Auswahl von Assemble. Das Ergebnis des Vorganges öffnet ein
weiteres Fenster mit den Meldungen.

Tauchen hier Fehlermeldungen auf, dann ist Entwanzen angesagt.

Das Programm ist nun fertig assembliert und kann in den Zielchip programmiert werden. Das ist hier
nicht beschrieben.

Zum Seitenanfang

Simulieren des Programmablaufes


Bei hartnäckigen Wanzen oder komplexeren Abläufen lohnt sich das Simulieren des Programmes
oder seiner Teile im Simulator.
In diesem Fall wählen wir Build and Run. In unserem Quelltext erscheint dann ein kleiner gelber
Marker, der auf die nächste auszuführende Quelltextzeile zeigt.

Mit der Taste F11 starten wir schrittweise das Abarbeiten des Quelltextes. Damit wir den Forschritt
erkennen können, öffnen wir eine Registeransicht. Der LDI-Befehl schreibt hex-FF in das Register
R16.

Der nächste Befehl schreibt in das Datenrichtungsregister von Port B. Diesen Port können wir uns
anzeigen lassen. Er zeigt nach dem OUT-Befehl den Inhalt des DDRB so an:

Nach dem zweiten OUT-Befehl (hex-AA an Port D) tut sich auch am Port-Datenregister etwas.

Für die Simulation gibt es eine Reihe weiterer Ansichten und Möglichkeiten, die hier nicht im Detail
beschrieben werden sollen.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/studio352.html1/20/2009 7:33:35 PM
http://www.avr-asm-tutorial.net/avr_gra/stu352.gif

http://www.avr-asm-tutorial.net/avr_gra/stu352.gif1/20/2009 7:33:40 PM
http://www.avr-asm-tutorial.net/avr_gra/newproj.gif

http://www.avr-asm-tutorial.net/avr_gra/newproj.gif1/20/2009 7:33:41 PM
http://www.avr-asm-tutorial.net/avr_gra/projnew.gif

http://www.avr-asm-tutorial.net/avr_gra/projnew.gif1/20/2009 7:33:43 PM
http://www.avr-asm-tutorial.net/avr_gra/newfile.gif

http://www.avr-asm-tutorial.net/avr_gra/newfile.gif1/20/2009 7:33:44 PM
http://www.avr-asm-tutorial.net/avr_gra/edit.gif

http://www.avr-asm-tutorial.net/avr_gra/edit.gif1/20/2009 7:33:45 PM
http://www.avr-asm-tutorial.net/avr_gra/asm.gif

http://www.avr-asm-tutorial.net/avr_gra/asm.gif1/20/2009 7:33:50 PM
http://www.avr-asm-tutorial.net/avr_gra/sim1.gif

http://www.avr-asm-tutorial.net/avr_gra/sim1.gif1/20/2009 7:33:53 PM
http://www.avr-asm-tutorial.net/avr_gra/regs1.gif

http://www.avr-asm-tutorial.net/avr_gra/regs1.gif1/20/2009 7:33:55 PM
http://www.avr-asm-tutorial.net/avr_gra/io2.gif

http://www.avr-asm-tutorial.net/avr_gra/io2.gif1/20/2009 7:33:58 PM
http://www.avr-asm-tutorial.net/avr_gra/io3.gif

http://www.avr-asm-tutorial.net/avr_gra/io3.gif1/20/2009 7:34:00 PM
Programmplanung in Assembler

Pfad: Home => AVR-Überblick => Programmiertechniken => Projektplanung

Programmiertechnik für Anfänger in AVR


Assemblersprache
Wie plane ich ein Projekt in Assembler?
Hier wird erklärt, wie man ein einfaches Projekt plant, das in Assembler programmiert werden soll.
Weil die verwendeten Hardwarekmponenten eines Prozessors sehr vieles vorweg bestimmen, was
und wie die Hard- und Software aufgebaut werden muss, zunächst die Überlegungen zur Hardware.
Dann folgt ein Kapitel zur Entscheidung über den Einsatz von Interrupts und schließlich Einiges über
Timing.

Überlegungen zur Hardware

In die Entscheidung, welchen AVR-Typ man verwendet, gehen eine Vielzahl an Anforderungen ein.
Hier einige häufiger vorkommende Forderungen zur Auswahl:

1. Welche festen Portanschlüsse werden gebraucht? Feste Portanschlüsse sind Ein- oder
Ausgänge von internen Komponenten, die an ganz bestimmten Anschlüssen liegen müssen
und nicht frei wählbar sind. Sie werden zuerst zugeordnet. Komponenten und Anschlüsse
dieser Art sind:
1. Soll der Prozessor in der Schaltung programmiert werden können (ISP-Interface), dann
werden die Anschlüsse SCK, MOSI und MISO diesem Zweck fest zugeordnet. Bei
entsprechender Hardwaregestaltung können diese als Eingänge (SCK, MOSI) oder als
Ausgang doppelt verwendet werden (Entkopplung über Widerstände oder Multiplexer
empfohlen).
2. Wird eine serielle Schnittstelle benötigt, sind RXD und TXD dafür zu reservieren. Soll
zusätzlich das RTS/CTS-Hardware-Protokoll implementiert werden, sind zusätzlich
zwei weitere Portbits dafür zu reservieren, die aber frei platziert werden können.
3. Soll der Analogkomparator verwendet werden, dann sind AIN0 und AIN1 dafür zu
reservieren.
4. Sollen externe Signale auf Flanken überwacht werden, dann sind INT0 bzw. INT1
dafür zu reservieren.
5. Sollen AD-Wandler verwendet werden, müssen entsprechend der Anzahl benötigter
Kanäle die Eingänge dafür vorgesehen werden. Verfügt der AD-Wandler über die
externen Anschlüsse AVCC und AREF, sollten sie entsprechend extern beschaltet
werden.
6. Sollen externe Impulse gezählt werden, sind dafür die Timer-Input-Anschlüsse T0, T1
bzw. T2 zu reservieren. Soll die Dauer externer Impulse exakt gemessen werden, ist
dafür der ICP-Eingang zu verwenden. Sollen Timer-Ausgangsimpulse mit definierter
Pulsdauer ausgegeben werden, sind die entsprechenden OCx-Ausgänge dafür zu
reservieren.
7. Wird externer SRAM-Speicher benötigt, müssen alle nötigen Address- und Datenports
sowie ALE, RD und WR dafür reserviert werden.
8. Soll der Takt des Prozessors aus einem externen Oszillatorsignal bezogen werden, ist
XTAL1 dafür zu reservieren. Soll ein externer Quarz den Takt bestimmen, sind die
Anschlüsse XTAL1 und XTAL2 dafür zu verwenden.
2. Welche zusammenhängenden Portanschlüsse werden gebraucht? Zusammenhängende
Portanschlüsse sind solche, bei denen zwei oder mehr Bits in einer bestimmten Reihenfolge
angeordnet sein sollten, um die Software zu vereinfachen.
1. Erfordert die Ansteuerung eines externen Gerätes das Schreiben oder Lesen von mehr
als einem Bit gleichzeitig, z.B. eine vier- oder achtbittige LCD-Anzeige, sollten die
nötigen Portbits in dieser Reihenfolge platziert werden. Ist das z.B. bei achtbittigen
Interfaces nicht möglich, können auch zwei vierbittige Interfaces vorgesehen werden.
Die Software wird vereinfacht, wenn diese 4-Bit-Interfaces links- bzw. rechtsbündig im
Port angeordnet sind.
2. Werden zwei oder mehr ADC-Kanäle benötigt, sollten diese in einer direkten Abfolge
(z.B. ADC2/ADC3/ADC4) platziert werden, um die Ansteuerungssoftware zu
vereinfachen.
3. Welche frei platzierbaren Portbits werden noch gebraucht? Jetzt wird alles zugeordnet, was
keinen bestimmten Platz braucht.
1. Wenn es jetzt wegen eines einzigen Portbits eng wird, kann der RESET-Pin bei einigen
Typen als Eingang verwendet werden, indem die entsprechende Fuse gesetzt wird. Da
der Chip anschließend nur noch über Hochvolt-Programmierung zugänglich ist, ist dies
für fertig getestete Software akzeptabel. Für Prototypen in der Testphase ist für ISP ein
Hochvolt-Programmier-Interface am umdefinierten RESET-Pin und eine
Schutzschaltung aus Widerstand und Zenerdiode gegenüber der Signalquelle vonnöten
(beim HV-Programmieren treten +12 Volt am RESET-Pin auf).

In die Entscheidung, welcher Prozessortyp für die Aufgabe geeignet ist, gehen ferner noch ein:

● Wieviele und welche Timer werden benötigt?


● Welche Werte sind beim Abschalten des Prozessors zu erhalten (EEPROM dafür vorsehen)?
● Wieviel Speicher wird im laufenden Betrieb benötigt (entsprechend SRAM dafür vorsehen)?
● Platzbedarf? Bei manchen Projekten mag der Platzbedarf des Prozessors ein wichtiges
Entscheidungskriterium sein.
● Strombedarf? Bei Batterie-/Akku-betriebenen Projekten sollte der Strombedarf ein wichtiges
Auswahlkriterium sein.
● Preis? Spielt nur bei Großprojekten eine wichtige Rolle. Ansonsten sind Preisrelationen recht
kurzlebig und nicht unbedingt von der Prozessorausstattung abhängig.
● Verfügbarkeit? Wer heute noch ein Projekt mit dem AT90S1200 startet, hat ihn vielleicht als
Restposten aus der Grabbelecke billig gekriegt. Nachhaltig ist so eine Entscheidung nicht. Es
macht wesentlich mehr Mühe, so ein Projekt auf einen Tiny- oder Mega-Typen zu portieren
als der Preisvorteil heute wert ist. Das "Portieren" endet daher meist mit einer kompletten
Neuentwicklung, die dann auch schöner aussieht, besser funktioniert und mit einem Bruchteil
des Codes auskommt.

Zum Seitenanfang

Überlegungen zum Interrupt-Betrieb

Einfachste Projekte kommen ohne Interrupt aus. Wenn allerdings der Strombedarf minimiert werden
soll, dann auch dann nicht. Es ist daher bei fast allen Projekten die Regel, dass eine
Interruptsteuerung nötig ist. Und die will sorgfältig geplant sein.

Grundanforderungen des Interrupt-Betriebs

Falls es nicht mehr parat ist, hier ein paar Grundregeln:

● Interrupts ermöglichen:
❍ Interruptbetrieb erfordert einen eingerichteten SRAM-Stapel! ==> SPH:SPL sind zu

Beginn auf RAMEND gesetzt, der obere Teil des SRAM (je nach Komplexität und
anderweitigem Stapeleinsatz 8 bis x Byte) bleibt dafür freigehalten!
❍ Jede Komponente (z.B. Timer) und jede Bedingung (z.B. ein Overflow), die einen

Interrupt auslösen soll, wird durch Setzen des entsprechenden Interrupt-Enable-Bits in


seinen Steuerregistern dazu ermutigt, dies zu tun.
❍ Das I-Flag im Statusregister SREG wird zu Beginn gesetzt und bleibt möglichst

während des gesamten Betriebs gesetzt. Ist es bei einer Operation nötig, Interrupts zu
unterbinden, wird das I-Flag kurz zurückgesetzt und binnen weniger Befehlsworte
wieder gesetzt.
● Interrupt-Service-Tabelle:
❍ Jeder Komponente und jeder gesetzten Interruptbedingung ist eine Interrupt-Service-

Routine zugeordnet, die an einer ganz bestimmten Addresse im Flash-Speicher beginnt.


Die Speicherstelle erfordert an dieser Stelle einen Ein-Wort-Sprung in die eigentliche
Service-Routine (RJMP; bei sehr großen ATmega sind Zwei-Wort-Sprünge - JMP -
vorgesehen).
❍ Die ISR-Addressen sind prozessortyp-spezifisch angeordnet! Beim Portieren zu einem

anderen Prozessortyp sind diese Addressen entsprechend anzupassen.


❍ Jede im Programm nicht verwendete ISR-Adresse wird mit einem RETI abgeschlossen,

damit versehentlich eingeschaltete Enable-Bits von Komponenten definiert


abgeschlossen sind und keinen Schaden anrichten könen. Die Verwendung der .ORG-
Direktive zum Einstellen der ISR-Addresse ist KEIN definierter Abschluss!
❍ Beim Vorliegen der Interrupt-Bedingung wird in den Steuerregistern der

entsprechenden Komponente ein Flag gesetzt, das im Allgemeinen nach dem


Anspringen der Interrupt-Service-Tabelle automatisch wieder gelöscht wird. In
wenigen Ausnahmefällen kann es nötig sein (z.B. beim TX-Buffer-Empty-Interrupt der
SIO, wenn kein weiteres Zeichen gesendet werden soll), den Interrupt-Enable
abzuschalten und das bereits erneut gesetzte Flag zu löschen.
❍ Bei gleichzeitig eintreffenden Interrupt-Service-Anforderungen sind die ISR-

Addressen nach Prioritäten geordnet: die ISR mit der niedrigsten Addresse in der
Tabelle wird bevorzugt ausgeführt.
● Interrupt-Service-Routinen:
❍ Jede Service-Routine beginnt mit der Sicherung des Prozessor- Statusregisters in einem

für diesen Zweck reservierten Register und endet mit der Wiederherstellung des Status.
Da die Unterbrechung zu jeder Zeit erfolgen kann, - also auch zu einer Zeit, in der der
Prozessor mit Routinen des Hauptprogramms beschäftigt ist, die das Statusregister
verwenden, - kann eine Störung dieses Registers unvorhersehbare Folgen haben.
❍ Beim Ansprung der ISR wird die Rücksprungaddresse auf dem Stapel abgelegt, der

dadurch nach niedrigeren Addressen hin wächst. Der Interrupt und das Anspringen
einer Interrupt-Service-Tabelle schaltet die Ausführung weiterer anstehender Interrupts
zunächst ab. Jede Interrupt-Service-Routine endet daher mit der Instruktion RETI, die
den Stapel wieder in Ordnung bringt und die Interrupts wieder zulässt.
❍ Da jede Interrupt-Service-Routine anstehende weitere Interrupts solange blockiert, wie

sie selbst zu ihrer Ausführung benötigt, hat jede Interrupt-Service-Routine so kurz wie
nur irgend möglich zu sein und sich auf die zeitkritischen Operationen zu beschränken.
❍ Da auch Interrupts mit höherer Priorität blockiert werden, sollte bei zeitkritischen

Operationen niedriger prioritäre Ints besonders kurz sein.


❍ Da eine erneute Unterbrechung während der Verarbeitung einer Service-Routine nicht

vorkommen kann, können in den verschiedenen ISR-Routinen die gleichen temporären


Register verwendet werden.
● Schnittstelle Interrupt-Routine und Hauptprogramm:
❍ Die Kommunikation zwischen der Interruptroutine und dem Hauptprogramm erfolgt

über einzelne Flaggen, die in der ISR gesetzt und im Hauptprogramm wieder
zurückgesetzt werden. Zum Rücksetzen der Flaggen kommen ausschließlich Ein-Wort-
Instruktionen zum Einsatz oder Interrupts werden vorübergehend blockiert, damit
während des Rücksetzvorgangs diese oder andere Flaggen im Register bzw. im SRAM
nicht fälschlich überschrieben werden.
❍ Werte aus der Service-Routine werden in dezidierten Registern oder SRAM-

Speicherzellen übergeben. Jede Änderung von Register- oder SRAM-Werten innerhalb


der Service-Routine, die außerhalb des Interrupts weiterverarbeitet werden, ist
daraufhin zu prüfen, ob bei der Übergabe durch weitere Interrupts Fehler möglich sind.
Die Übergabe und Weiterverabeitung von Ein-Byte-Werten ist unproblematisch, bei
Übergabe von zwei und mehr Bytes ist ein eindeutiger Übergabemechanismus
zwingend (Interrupt Disable beim Kopieren der Daten in der Hauptprogramm-Schleife,
Flag-Setzen/-Auswerten/-Rücksetzen, o.ä.)! Als Beispiel sei der
Übergabemechanismus eines 16-Bit-Wertes von einem Timer/Counter an die
Auswerteroutine beschrieben. Der Timer schreibt die beiden Bytes in zwei Register
und setzt ein Flag in einem anderen Register, dass Werte zur Weiterverarbeitung
bereitstehen. Im Hauptprogramm wird dieses Flag ausgewertet, zurückgesetzt und die
Übergabe des Wertes gestartet. Wenn nun das erste Byte kopiert ist und erneut ein
Interrupt des Timers/Counters zuschlägt, gehören anschließend Byte 1 und Byte 2 nicht
zum gleichen Wertepaar. Das gilt es durch definierte Übergabemechanismen zu
verhindern!
● Die Hauptprogramm-Routinen:
❍ Im Hauptprogramm legt ein Loop den Prozessor schlafen, wobei der Schlafmodus

"Idle" eingestellt sein muss. Jeder Interrupt weckt den Prozessor auf, verzweigt zur
Service-Routine und setzt nach deren Beendigung die Verarbeitung fort. Es macht
Sinn, nun die Flags darauf zu überprüfen, ob eine oder mehrere der Service-Routinen
Bedarf an Weiterverarbeitung signalisiert hat. Wenn ja, wird entsprechend dorthin
verzweigt. Nachdem alle Wünsche der ISRs erfüllt sind, wird der Prozessor wieder
schlafen gelegt.

Grundaufbau im Interrupt-Betrieb

Aus dem Dargestellten ergibt sich die folgende Grundstruktur eines Interrupt- getriebenen
Programmes an einem Beispiel:

;
; Registerdefinitionen
;
.EQU rsreg = R15 ; Status-Sicherungs-Register bei Interrupts
.EQU rmp = R16 ; Temporäres Register auäerhalb von Interrupts
.EQU rimp = R17 ; Temporäres Register innerhalb von Interrupts
.EQU rflg = R18 ; Flaggenregister zur Kommunikation
.EQU bint0 = 0 ; Flaggenbit zur Signalisierung INT0-Service
.EQU btc0 = 1 ; Flaggenbit zur Signalisierung TC0-Overflow
; ...
; ISR-Tabelle
;
.CSEG
.ORG $0000
rjmp main ; Reset-Vektor, wird beim Start ausgeführt
rjmp isr_int0 ; INT0-Vektor, wird bei eine Pegeländerung am
INT0-Eingang ausgefürt
reti ; nicht belegter Interrupt
reti ; nicht belegter Interrupt
rjmp isr_tc0_Overflow ; TC0-Overflow-Vektor, wird bei
Überlauf TC0 ausgeführt
reti ; nicht belegter Interrupt
reti ; nicht belegter Interrupt
; ... gegebenenfalls weitere ISR
;
; Interrupt-Service-Routinen
;
isr_int0: ; INT0-Service Routine
in rsreg,SREG ; sichere Status
in rimp,PINB ; lese Port B in Temp Register
out PORTC,rimp ; schreibe Temp Register in Port C
; ... mache irgendwas weiteres
sbr rflg,1<<bint0 ; signalisiere INT0 nach außerhalb
out SREG,rsreg ; stelle Status wieder her
reti ; Sprung zurück und Int wieder zulassen
isr_tc0_Overflow: ; TC0 Overflow Service Routine
in rsreg,SREG ; sichere Status
in rimp,PINB ; lese Port B in Temp Register
out PORTC,rimp ; schreibe Temp Register in Port C
; ... mache irgendwas weiteres
sbr rflg,1<<btc0 ; setze TC0-Weiterbehandlungs-Flagge
out SREG,rsreg ; stelle Status wieder her
reti ; Sprung zurück und Int wieder zulassen
;
; Hauptprogramm-Start
;
main:
ldi rmp,HIGH(RAMEND) ; setze Stapelregister
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; ... weiteres
; INT Enable bei TC0 Overflow
ldi rmp,1<<TOIE0 ; Overflow Interrupt Enable Timer 0
out TIMSK,rmp ; Interrupt-Maske der Timer setzen
ldi rmp,(1<<CS00)|(1<<CS02) ; Teiler durch 1024
out TCCR0,rmp ; Timer starten
; INT Enable beim INT0-Eingang
ldi rmp,(1<<SE)|(1<<ISC00) ; SLEEP-Enable und INT0 bei
allen Flanken
out MCUCR,rmp ; an das Kontrollregister
ldi rmp,1<<INT0 ; INT0 ermöglichen
out GICR,rmp ; im Interrupt-Kontrollregister
; Interrupt Status Flag setzen
sei ; setze Interrupts an
;
; Hauptprogramm-Loop
;
loop:
sleep ; schlafen legen
nop ; Dummy nach dem Aufwachen
sbrc rflg,bint0 ; keine INT0-Anforderung
rcall mache_int0 ; behandle INT0-Ergebnis
sbrc rflg,btc0 ; keine TC0-Overflow-Behandlung
rcall mache_tc0 ; behandle TC0-Overflow
rjmp loop ; lege dich wieder schlafen
;
; Behandlung der Anforderungen
;
mache_int0: ; Behandle INT0-Ergebnis
cbr rflg,1<<bint0 ; Setze INT0-Flagge zurück
; ... mache weiteres
ret ; fertig, zurück zum Loop
mache_tc0: ; Behandle TC0-Overflow
cbr rflg,1<<btc0 ; Setze TC0-Flage wieder zurück
; ... mache weiteres
ret ; fertig, zurück zum Loop

Zum Seitenanfang

Überlegungen zum Timing

Geht ein Projekt darüber hinaus, ein Portbit abzufragen und daraus abgeleitet irgendwas anderes zu
veranlassen, dann sind Überlegungen zum Timing des Projektes zwinged. Timing

● beginnt mit der Wahl der Taktfrequenz des Prozessors,


● geht weiter mit der Frage, was wie häufig und mit welcher Präzision vom Prozesser erledigt
werden muss,
● über die Frage, welche Timing-Steuerungsmöglichkeiten bestehen, bis zu
● wie diese kombiniert werden können.

Wahl der Taktfrequenz des Prozessors

Die oberste Grundfrage ist die nach der nötigen Präzision des Taktgebers.

Reicht es in der Anwendung, wenn die Zeiten im Prozentbereich ungenau sind, dann ist der interne
RC-Oszillator in vielen AVR-Typen v&oml;llig ausreichend. Bei den neueren ATtiny und ATmega
hat sich die selbsttätige Oszillator-Kalibration eingebürgert, so dass die Abweichungen vom
Nominalwert des RC-Oszillators nicht mehr so arg ins Gewicht fallen. Wenn allerdings die
Betriebsspannung stark schwankt, kann der Fehler zu groß sein.

Wem der interne RC-Takt zu langsam oder zu schnell ist, kann bei einigen neueren Typen (z.B. dem
ATtiny13) einen Vorteiler bemühen. Der Vorteiler geht beim Anlegen der Betriebsspannung auf
einen voreingestellten Wert (z.B. auf 8) und teilt den internen RC-Oszillator entsprechend vor.
Entweder per Fuse-Einstellung oder auch per Software-Einstellung kann der Vorteiler auf niedrigere
Teilerverhältnisse (höhere Taktfrequenz) oder auf einen höheren Wert umgestellt werden (z.B. 128),
um durch niedrigere Taktfrequenz z.B. verst&aum;rkt Strom zu sparen. Obacht bei V-Typen! Wer
dem Prozessor einen zu hohen Takt zumutet, hat es nicht anders verdient als dass der Prozessor nicht
tut, was er soll.

Wem der interne RC-Oszillator zu ungenau ist, kann per Fuse eine externe RC-Kombination, einen
externen Oszillator, einen Quarz oder einen Keramikschwinger auswählen. Gegen falsch gesetzte
Fuses ist kein Kraut gewachsen, es muss dann schon ein Board mit eigenem Oszillator sein, um doch
noch was zu retten.

Die Höhe der Taktfrequenz sollte der Aufgabe angemessen sein. Dazu kann grob die
Wiederholfrequenz der Tätigkeiten dienen. Wenn eine Taste z.B. alle 2 ms abgefragt werden soll und
nach 20 Mal als entprellt ausgeführt werden soll, dann ist bei einer Taktfrequenz von 1 MHz für
2000 Takte zwischen zwei Abfragen Platz, 20.000 Takte für die wiederholte Ausführung des
Tastenbefehls. Weit ausreichend für eine gemütliche Abfrage und Ausführung.

Eng wird es, wenn eine Pulsweitenmodulation mit hoher Auflösung und hoher PWM-Taktfrequenz
erreicht werden soll. Bei einer PWM-Taktfrequenz von 10 kHz und 8 Bit Auflösung sind 2,56 MHz
schon zu langsam für eine software-gesteuerte Lösung. Wenn das ein Timer mit Interrupt-Steuerung
übernimmt, um so besser.

Was ist wann und wie zu tun?

Mit welchen Methoden lässt sich das machen?

Zum Seitenanfang

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/beginner/planung.html1/20/2009 7:34:03 PM
Binäres Rechnen in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen

Binäres Rechnen in AVR Assembler


Diese Seite zeigt, wie Rechnen mit Binärzahlen in AVR Assembler
funktioniert. An einfachen Beispielen werden die Grundrechenarten
Multiplikation und Division sowie die Zahlenumwandlung erläutert. An zwei Beispielen wird der
Umgang mit Fließkommazahlen erläutert. Die Hardware-Multiplikation mit ATmega wird gezeigt.

1. Multiplikation zweier 8-Bit-Zahlen


❍ Dezimales Multiplizieren als Vorlage

❍ Binäres Multiplizieren

❍ Assemblerprogramm Multiplikation

❍ Rotieren in Assembler

❍ Multiplikation im Studio

2. Division einer 16-Bit-Zahl durch eine 8-Bit-Zahl


❍ Dezimale Division als Vorlage

❍ Binäre Division

❍ Binäre Division im Simulator

3. Umwandlungen von und zu Binärzahlen


❍ Allgemeines zur Formatumwandlung

❍ Zahlenformate und allgemeine Programmierregeln

❍ ASCII nach Binär

❍ BCD nach Binär

❍ Binärzahl mit 10 multiplizieren

❍ Binär nach ASCII

❍ Binär nach BCD

❍ Binär nach Hex-ASCII

❍ Hex-ASCII nach Binär

4. Rechnen mit Festkommazahlen


❍ Sinn und Unsinn von Fließkommazahlen

❍ Lineare Umrechnungen

❍ Beispiel 1: 8-Bit-AD-Wandler zu 0,00 bis 5,00 Volt

❍ Beispiel 2: 10-Bit-AD-Wandler zu 0,000 bis 5,000 Volt

5. Hardware Multiplikation mit ATmega


❍ 8- mal 8-Bit-Multiplikation

❍ 16- mal 8-Bit-Multiplikation

❍ 16- mal 16-Bit-Multiplikation

❍ 16- mal 24-Bit-Multiplikation

Zum Seitenanfang

©2002-2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/index.html1/20/2009 7:34:05 PM
Binäre Multiplikation in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Multiplikation

Binäres Multiplizieren zweier 8-Bit-


Zahlen in AVR Assembler
Dezimales Multiplizieren
Zwei 8-Bit-Zahlen sollen multipliziert werden. Man erinnere sich, wie das mit Dezimalzahlen geht:

1234 * 567 = ?
------------------------
1234 * 7 = 8638
+ 12340 * 6 = 74040
+ 123400 * 5 = 617000
------------------------
1234 * 567 = 699678
========================

Also in Einzelschritten dezimal:


1. Wir nehmen die Zahl mit der kleinsten Ziffer mal und addieren sie zum Ergebnis.
2. Wir nehmen die Zahl mit 10 mal, dann mit der nächsthöheren Ziffer, und addieren sie zum
Ergebnis.
3. Wir nehmen die Zahl mit 100 mal, dann mit der dritthöchsten Ziffer, und addieren sie zum
Ergebnis.

Binäres Multiplizieren
Jetzt in Binär: Das Malnehmen mit den Ziffern entfällt, weil es ja nur Null oder Eins gibt, also
entweder wird die Zahl addiert oder eben nicht. Das Malnehmen mit 10 wird in binär zum
Malnehmen mit 2, weil wir ja nicht mit Basis 10 sondern mit Basis 2 rechnen. Malnehmen mit 2 ist
aber ganz einfach: man kann die Zahl einfach mit sich selbst addieren oder binär nach links schieben
und rechts eine binäre Null dazu schreiben. Man sieht schon, dass das binäre Multiplizieren viel
einfacher ist als das dezimale Multiplizieren. Man fragt sich, warum die Menschheit so ein
schrecklich kompliziertes Dezimalsystem erfinden musste und nicht beim binären System verweilt ist.

AVR-Assemblerprogramm
Die rechentechnische Umsetzung in AVR-Assembler-Sprache zeigt der Quelltext in HTML. Wer den
Quelltext direkt haben möchte, findet ihn in der Datei mult8.asm. Der Quelltext kann mit einem
Assembler übersetzt werden, der Object-Code im Studio durchgespielt werden.

Zu Beginn der Berechnung liegen die folgenden Bedingungen vor (wechseln Sie Ihren Browser,
wenn diese Tabelle nicht korrekt angezeigt wird!):

. rmh = R1 = 0x00 rm1 = R0 = 0xAA


Z1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0
* . rm2 = R2 = 0x55
Z2 0 1 0 1 0 1 0 1
= reh = R4 = 0x00 rel = R3 = 0x00
Erg 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Binäres Rotieren
Für das Verständnis der Berechnung ist die Kenntnis des Assembler-Befehles ROL bzw ROR
wichtig. Der Befehl verschiebt die Bits eines Registers nach links (ROL) bzw. rechts (ROR), schiebt
das Carry-Bit aus dem Statusregister in die leer werdende Position im Register und schiebt dafür das
beim Rotieren herausfallende Bit in das Carry-Flag. Dieser Vorgang wird für das Linksschieben mit
dem Inhalt des Registers von 0xAA, für das Rechtsschieben mit 0x55 gezeigt:

Multiplikation im Studio
Die folgenden Bilder zeigen die einzelnen Schritte im Studio:

1. MULT8_1.gif: Der Object-Code ist gestartet, der Cursor steht auf dem ersten Befehl. Mit F11
machen wir Einzelschritte.
2. MULT8_2.gif: In die Register R0 und R2 werden die beiden Werte AA und 55 geschrieben,
die wir multiplizieren wollen.
3. MULT8_3.gif: R2 wurde nach rechts geschoben, um das niedrigste Bit in das Carry-Bit zu
schieben. Aus 55 (0101.0101) ist 2A geworden (0010.1010), die rechteste 1 liegt im Carry-Bit
des Status-Registers herum.
4. MULT8_4.gif: Weil im Carry eine Eins war, wird 00AA in den Registern R1:R0 zu dem
(leeren) Registerpaar R4:R3 hinzu addiert. 00AA steht nun auch dort herum.
5. MULT8_5.gif: Jetzt muss das Registerpaar R1:R0 mit sich selbst addiert oder in unserem Fall
einmal nach links geschoben werden. Aus 00AA (0000.0000.1010.1010) wird jetzt 0154
(0000.0001.0101.0100), weil wir von rechts eine Null hinein geschoben haben.
6. Die gesamte Multiplikation geht solange weiter, bis alle Einsen in R2 durch das
Rechtsschieben herausgeflogen sind. Die Zahl ist dann fertig multipliziert, wenn nur noch
Nullen in R2 stehen. Die weiteren Schritte sind nicht mehr abgebildet.
7. MULT8_6.gif: Mit F5 haben wir im Simulator den Rest durchlaufen lassen und sind am
Ausgang der Multiplikationsroutine angelangt, wo wir einen Breakpoint gesetzt hatten. Das
Ergebnisregister R4:R3 enthält nun den Wert 3872, das Ergebnis der Multiplikation von AA
mit 55.

Das war sicherlich nicht schwer, wenn man sich die Rechengänge von Dezimal in Binär übersetzt.
Binär ist viel einfacher als Dezimal!

Zum Seitenanfang

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/multiplikation.html1/20/2009 7:34:08 PM
Multiplikation zweier 8-Bit-Zahlen

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Multiplikation

Assembler Quelltext der Multiplikation


; Mult8.asm multipliziert zwei 8-Bit-Zahlen
; zu einem 16-Bit-Ergebnis
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Ablauf des Multiplizierens:
;
; 1.Multiplikator 2 wird bitweise nach rechts in das
; Carry-Bit geschoben. Wenn es eine Eins ist, dann
; wird die Zahl in Multiplikator 1 zum Ergebnis dazu
; gezählt, wenn es eine Null ist, dann nicht.
; 2.Nach dem Addieren wird Multiplikator 1 durch Links-
; schieben mit 2 multipliziert.
; 3.Wenn Multiplikator 2 nach dem Schieben nicht Null
; ist, dann wird wie oben weiter gemacht. Wenn er Null
; ist, ist die Multplikation beendet.
;
; Benutzte Register
;
.DEF rm1 = R0 ; Multiplikator 1 (8 Bit)
.DEF rmh = R1 ; Hilfsregister für Multiplikation
.DEF rm2 = R2 ; Multiplikator 2 (8 Bit)
.DEF rel = R3 ; Ergebnis, LSB (16 Bit)
.DEF reh = R4 ; Ergebnis, MSB
.DEF rmp = R16 ; Hilfsregister zum Laden
;
.CSEG
.ORG 0000
;
rjmp START
;
START:
ldi rmp,0xAA ; Beispielzahl 1010.1010
mov rm1,rmp ; in erstes Multiplikationsreg
ldi rmp,0x55 ; Beispielzahl 0101.0101
mov rm2,rmp ; in zweites Multiplikationsreg
;
; Hier beginnt die Multiplikation der beiden Zahlen
; in rm1 und rm2, das Ergebnis ist in reh:rel (16 Bit)
;
MULT8:
;
; Anfangswerte auf Null setzen
clr rmh ; Hilfsregister leeren
clr rel ; Ergebnis auf Null setzen
clr reh
;
; Hier beginnt die Multiplikationsschleife
;
MULT8a:
;
; Erster Schritt: Niedrigstes Bit von Multplikator 2
; in das Carry-Bit schieben (von links Nullen nachschieben)
;
clc ; Carry-Bit auf Null setzen
ror rm2 ; Null links rein, alle Bits eins rechts,
; niedrigstes Bit in Carry schieben
;
; Zweiter Schritt: Verzweigen je nachdem ob eine Null oder
; eine Eins im Carry steht
;
brcc MULT8b ; springe, wenn niedrigstes Bit eine
; Null ist, über das Addieren hinweg
;
; Dritter Schritt: Addiere 16 Bits in rmh:rm1 zum Ergebnis
; in reh:rel (mit Überlauf der unteren 8 Bits!)
;
add rel,rm1 ; addiere LSB von rm1 zum Ergebnis
adc reh,rmh ; addiere Carry und MSB von rm1
;
MULT8b:
;
; Vierter Schritt: Multipliziere Multiplikator rmh:rm1 mit
; Zwei (16-Bit, links schieben)
;
clc ; Carry bit auf Null setzen
rol rm1 ; LSB links schieben (multiplik. mit 2)
rol rmh ; Carry in MSB und MSB links schieben
;
; Fünfter Schritt: Prüfen, ob noch Einsen im Multi-
; plikator 2 enthalten sind, wenn ja, dann weitermachen
;
tst rm2 ; alle bits Null?
brne MULT8a ; wenn nicht null, dann weitermachen
;
; Ende der Multiplikation, Ergebnis in reh:rel
;
; Endlosschleife
;
LOOP:
rjmp loop

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/mult8.html1/20/2009 7:34:10 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/mult8.asm

; Mult8.asm multipliziert zwei 8-Bit-Zahlen


; zu einem 16-Bit-Ergebnis
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Ablauf des Multiplizierens:
;
; 1.Multiplikator 2 wird bitweise nach rechts in das
; Carry-Bit geschoben. Wenn es eine Eins ist, dann
; wird die Zahl in Multiplikator 1 zum Ergebnis dazu
; gezählt, wenn es eine Null ist, dann nicht.
; 2.Nach dem Addieren wird Multiplikator 1 durch Links-
; schieben mit 2 multipliziert.
; 3.Wenn Multiplikator 2 nach dem Schieben nicht Null
; ist, dann wird wie oben weiter gemacht. Wenn er Null
; ist, ist die Multplikation beendet.
;
; Benutzte Register
;
.DEF rm1 = R0 ; Multiplikator 1 (8 Bit)
.DEF rmh = R1 ; Hilfsregister für Multiplikation
.DEF rm2 = R2 ; Multiplikator 2 (8 Bit)
.DEF rel = R3 ; Ergebnis, LSB (16 Bit)
.DEF reh = R4 ; Ergebnis, MSB
.DEF rmp = R16 ; Hilfsregister zum Laden
;
.CSEG
.ORG 0000
;
rjmp START
;
START:
ldi rmp,0xAA ; Beispielzahl 1010.1010
mov rm1,rmp ; in erstes Multiplikationsreg
ldi rmp,0x55 ; Beispielzahl 0101.0101
mov rm2,rmp ; in zweites Multiplikationsreg
;
; Hier beginnt die Multiplikation der beiden Zahlen
; in rm1 und rm2, das Ergebnis ist in reh:rel (16 Bit)
;
MULT8:
;
; Anfangswerte auf Null setzen
clr rmh ; Hilfsregister leeren
clr rel ; Ergebnis auf Null setzen
clr reh
;
; Hier beginnt die Multiplikationsschleife
;
MULT8a:
;
; Erster Schritt: Niedrigstes Bit von Multplikator 2
; in das Carry-Bit schieben (von links Nullen nachschieben)
;
clc ; Carry-Bit auf Null setzen
ror rm2 ; Null links rein, alle Bits eins rechts,
; niedrigstes Bit in Carry schieben
;
; Zweiter Schritt: Verzweigen je nachdem ob eine Null oder
; eine Eins im Carry steht
;
brcc MULT8b ; springe, wenn niedrigstes Bit eine
; Null ist, über das Addieren hinweg
;
; Dritter Schritt: Addiere 16 Bits in rmh:rm1 zum Ergebnis
; in reh:rel (mit Überlauf der unteren 8 Bits!)
;
add rel,rm1 ; addiere LSB von rm1 zum Ergebnis
adc reh,rmh ; addiere Carry und MSB von rm1
;
MULT8b:
;
; Vierter Schritt: Multipliziere Multiplikator rmh:rm1 mit
; Zwei (16-Bit, links schieben)
;
clc ; Carry bit auf Null setzen
rol rm1 ; LSB links schieben (multiplik. mit 2)
rol rmh ; Carry in MSB und MSB links schieben
;
; Fünfter Schritt: Prüfen, ob noch Einsen im Multi-
; plikator 2 enthalten sind, wenn ja, dann weitermachen
;
tst rm2 ; alle bits Null?
brne MULT8a ; wenn nicht null, dann weitermachen
;
; Ende der Multiplikation, Ergebnis in reh:rel
;
; Endlosschleife
;
LOOP:
rjmp loop

http://www.avr-asm-tutorial.net/avr_de/quellen/mult8.asm1/20/2009 7:34:12 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_1.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_1.gif1/20/2009 7:34:16 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_2.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_2.gif1/20/2009 7:34:20 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_3.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_3.gif1/20/2009 7:34:23 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_4.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_4.gif1/20/2009 7:34:25 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_5.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_5.gif1/20/2009 7:34:28 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_6.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/MULT8_6.gif1/20/2009 7:34:32 PM
Binäres Rechnen in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Division

Division einer 16-Bit-Zahl durch eine


8-Bit-Zahl

Dezimales Dividieren
Zunächst wieder eine dezimale Division, damit das besser verständlich wird. Nehmen wir an, wir
wollen 5678 durch 12 teilen. Das geht dann etwa so:

5678 : 12 = ?
--------------------------
- 4 * 1200 = 4800
----
878
- 7 * 120 = 840
---
38
- 3 * 12 = 36
--
2
Ergebnis: 5678 : 12 = 473 Rest 2
================================

Binäres Dividieren
Binär entfällt wieder das Multiplizieren des Divisors (4 * 1200, etc.), weil es nur Einsen und Nullen
gibt. Dafür haben binäre Zahlen leider sehr viel mehr Stellen als dezimale. Die direkte Analogie wäre
in diesem Fall etwas aufwändig, weshalb die rechentechnische Lösung etwas anders aussieht.

Die Division einer 16-Bit-Zahl durch eine 8-Bit-Zahl in AVR Assembler ist in HTML-Format hier
und als Quellcode hier gezeigt.

Programmschritte beim Dividieren

Das Programm gliedert sich in folgende Teilschritte:

1. Definieren und Vorbelegen der Register mit den Testzahlen,


2. das Vorbelegen von Hilfsregistern (die beiden Ergebnisregister werden mit 0x0001 vorbelegt,
um das Ende der Division nach 16 Schritten elegant zu markieren!),
3. die 16-Bit-Zahl in rd1h:rd1l wird bitweise in ein Hilfsregister rd1u geschoben (mit 2
multipliziert), rollt dabei eine 1 links heraus, dann wird auf jeden Fall zur Subtraktion im
vierten Schritt verzweigt,
4. der Inhalt des Hilfsregisters wird mit der 8-Bit-Zahl in rd2 verglichen, ist das Hilfsregister
größer wird die 8-Bit-Zahl subtrahiert und eine Eins in das Carry-Bit gepackt, ist es kleiner
dann wird nicht subtrahiert und eine Null in das Carry-Bit gepackt,
5. der Inhalt des Carry-Bit wird in die Ergebnisregister reh:rel von rechts einrotiert,
6. rotiert aus dem Ergebnisregister eine Null links heraus, dann muss weiter dividiert werden und
ab Schritt 3 wird wiederholt (insgesamt 16 mal), rollt eine 1 heraus, dann sind wir fertig.

Für das Rotieren gilt das oben dargestellte Procedere (siehe oben, zum Nachlesen).

Das Dividieren im Simulator


Die folgenden Bilder zeigen die Vorgänge im Simulator, dem Studio. Dazu wird der Quellcode
assembliert und die Object-Datei in das Studio geladen.

1. DIV8D1.gif: Der Object-Code ist gestartet, der Cursor steht auf dem ersten Befehl. Mit F11
machen wir Einzelschritte.
2. DIV8D2.gif: In die Register R0, R1 und R3 werden die beiden Werte 0xAAAA und 0x55
geschrieben, die wir dividieren wollen.
3. DIV8D3.gif: Die Startwerte für das Hilfsregister werden gesetzt, das Ergebnisregisterpaar
wurde auf 0x0001 gesetzt.
4. DIV8D4.gif: R1:R0 wurde nach links in Hilfsregister R2 geschoben, aus 0xAAAA ist
0x015554 entstanden.
5. DIV8D5.gif: Weil 0x01 in R2 kleiner als 0x55 in R3 ist, wurde das Subtrahieren
übersprungen, eine Null in das Carry gepackt und in R5:R4 geschoben. Aus der
ursprünglichen 1 im Ergebnisregister R5:R4 ist durch das Linksrotieren 0x0002 geworden. Da
eine Null in das Carry herausgeschoben wurde, geht der nächste Befehl (BRCC) mit einem
Sprung zur Marke div8a und die Scleife wird wiederholt.
6. DIV8D6.gif: Nach dem 16-maligen Durchlaufen der Schleife gelangen wir schließlich an die
Endlosschleife am Ende der Division. Im Ergebnisregister R5:R4 steht nun das Ergebnis der
Division von 0xAAAA durch 0x55, nämlich 0x0202. Die Register R2:R1:R0 sind leer, es ist
also kein Rest geblieben. Bliebe ein Rest, könnten wir ihn mit zwei multiplizieren und mit der
8-Bit-Zahl vergleichen, um das Ergebnis vielleicht noch aufzurunden. Aber das ist hier nicht
programmiert.
7. DIV8D7.gif: Im Prozessor-View sehen wir nach Ablauf des gesamten Divisionsprozesses
immerhin 60 Mikrosekunden Prozessorzeit verbraucht.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/division.html1/20/2009 7:34:35 PM
Division einer 16-Bit-Zahl durch eine 8-Bit-Zahl

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Division

Assembler Quellcode der Division


; Div8 dividiert eine 16-Bit-Zahl durch eine 8-Bit-Zahl
; Test: 16-Bit-Zahl: 0xAAAA, 8-Bit-Zahl: 0x55
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers
;
.DEF rd1l = R0 ; LSB Divident
.DEF rd1h = R1 ; MSB Divident
.DEF rd1u = R2 ; Hifsregister
.DEF rd2 = R3 ; Divisor
.DEF rel = R4 ; LSB Ergebnis
.DEF reh = R5 ; MSB Ergebnis
.DEF rmp = R16; Hilfsregister zum Laden
;
.CSEG
.ORG 0
;
rjmp start
;
start:
;
; Vorbelegen mit den Testzahlen
;
ldi rmp,0xAA ; 0xAAAA in Divident
mov rd1h,rmp
mov rd1l,rmp
ldi rmp,0x55 ; 0x55 in Divisor
mov rd2,rmp
;
; Divieren von rd1h:rd1l durch rd2
;
div8:
clr rd1u ; Leere Hilfsregister
clr reh ; Leere Ergebnisregister
clr rel ; (Ergebnisregister dient auch als
inc rel ; Zähler bis 16! Bit 1 auf 1 setzen)
;
; Hier beginnt die Divisionsschleife
;
div8a:
clc ; Carry-Bit leeren
rol rd1l ; nächsthöheres Bit des Dividenten
rol rd1h ; in das Hilfsregister rotieren
rol rd1u ; (entspricht Multipliklation mit 2)
brcs div8b ; Eine 1 ist herausgerollt, ziehe ab
cp rd1u,rd2 ; Divisionsergebnis 1 oder 0?
brcs div8c ; Überspringe Subtraktion, wenn kleiner
div8b:
sub rd1u,rd2; Subtrahiere Divisor
sec ; Setze carry-bit, Ergebnis ist eine 1
rjmp div8d ; zum Schieben des Ergebnisses
div8c:
clc ; Lösche carry-bit, Ergebnis ist eine 0
div8d:
rol rel ; Rotiere carry-bit in das Ergebnis
rol reh
brcc div8a ; solange Nullen aus dem Ergebnis
; rotieren: weitermachen
; Ende der Division erreicht
stop:
rjmp stop ; Endlosschleife

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/div8d.html1/20/2009 7:34:37 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/div8d.asm

; Div8 dividiert eine 16-Bit-Zahl durch eine 8-Bit-Zahl


; Test: 16-Bit-Zahl: 0xAAAA, 8-Bit-Zahl: 0x55
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers
;
.DEF rd1l = R0 ; LSB Divident
.DEF rd1h = R1 ; MSB Divident
.DEF rd1u = R2 ; Hifsregister
.DEF rd2 = R3 ; Divisor
.DEF rel = R4 ; LSB Ergebnis
.DEF reh = R5 ; MSB Ergebnis
.DEF rmp = R16; Hilfsregister zum Laden
;
.CSEG
.ORG 0
;
rjmp start
;
start:
;
; Vorbelegen mit den Testzahlen
;
ldi rmp,0xAA ; 0xAAAA in Divident
mov rd1h,rmp
mov rd1l,rmp
ldi rmp,0x55 ; 0x55 in Divisor
mov rd2,rmp
;
; Divieren von rd1h:rd1l durch rd2
;
div8:
clr rd1u ; Leere Hilfsregister
clr reh ; Leere Ergebnisregister
clr rel ; (Ergebnisregister dient auch als
inc rel ; Zähler bis 16! Bit 1 auf 1 setzen)
;
; Hier beginnt die Divisionsschleife
;
div8a:
clc ; Carry-Bit leeren
rol rd1l ; nächsthöheres Bit des Dividenten
rol rd1h ; in das Hilfsregister rotieren
rol rd1u ; (entspricht Multipliklation mit 2)
brcs div8b ; Eine 1 ist herausgerollt, ziehe ab
cp rd1u,rd2 ; Divisionsergebnis 1 oder 0?
brcs div8c ; Überspringe Subtraktion, wenn kleiner
div8b:
sub rd1u,rd2; Subtrahiere Divisor
sec ; Setze carry-bit, Ergebnis ist eine 1
rjmp div8d ; zum Schieben des Ergebnisses
div8c:
clc ; Lösche carry-bit, Ergebnis ist eine 0
div8d:
rol rel ; Rotiere carry-bit in das Ergebnis
rol reh
brcc div8a ; solange Nullen aus dem Ergebnis
; rotieren: weitermachen
; Ende der Division erreicht
stop:
rjmp stop ; Endlosschleife

http://www.avr-asm-tutorial.net/avr_de/quellen/div8d.asm1/20/2009 7:34:38 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D1.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D1.gif1/20/2009 7:34:42 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D2.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D2.gif1/20/2009 7:34:45 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D3.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D3.gif1/20/2009 7:34:48 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D4.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D4.gif1/20/2009 7:34:51 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D5.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D5.gif1/20/2009 7:34:54 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D6.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D6.gif1/20/2009 7:34:57 PM
http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D7.gif

http://www.avr-asm-tutorial.net/avr_de/rechnen/DIV8D7.gif1/20/2009 7:35:19 PM
Zahlenumwandlung in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Zahlenumwandlung

Zahlenumwandlung in AVR-
Assembler

Das Umwandeln von Zahlen kommt in Assembler recht häufig vor, weil der Prozessor am liebsten
(und schnellsten) in binär rechnet, der dumme Mensch aber nur das Zehnersystem kann. Wer also aus
einem Assemblerprogramm heraus mit Menschen an einer Tastatur kommunizieren möchte, kommt
um Zahlenumwandlung nicht herum. Diese Seite befasst sich daher mit diesen Wandlungen zwischen
den Zahlenwelten, und zwar etwas detaillierter und genauer.

Wer gleich in die Vollen gehen möchte, kann sich direkt in den üppig kommentierten Quelltext
stürzen. Den gibt es über diesen Link im HTML-Format oder über diesen Link im Assemblerformat.

Allgemeine Bedingungen der Zahlenumwandlung


Die hier behandelten Zahlensysteme sind:

● Dezimal: Jedes Byte zu je acht Bit enthält eine Ziffer, die in ASCII formatiert ist. So
repräsentiert der dezimale Wert 48, in binär $30, die Ziffer Null, 49 die Eins, usw. bis 57 die
Neun. Die anderen Zahlen, mit denen ein Byte gefüllt werden kann, also 0 bis 47 und 58 bis
255, sind keine gültigen Dezimalziffern. (Warum gerade 48 die Null ist, hat mit
amerikanischen Militärfernschreibern zu tun, aber das ist eine andere lange Geschichte.)
● BCD-Zahlen: BCD bedeutet Binary Coded Decimal. Es ist ähnlich wie dezimale ASCII-
Zahlen, nur entspricht die BCD-dezimale Null jetzt tatsächlich dem Zahlenwert Null (und
nicht 48). Dementsprechend gehen die BCDs von 0 bis 9. Alles weitere, was noch in ein Byte
passen würde (10 .. 255) ist keine gültige Ziffer und gehört sich bei BCDs verboten.
● Binärzahlen: Hier gibt es nur die Ziffern 0 und 1. Von hinten gelesen besitzen sie jeweils die
Wertigkeit der Potenzen von 2, also ist die Binärzahl 1011 soviel wie 1* (2 hoch 0) + 1*(2
hoch 1) + 0*(2 hoch 2) + 1*(2 hoch 3), so ähnlich wie dezimal 1234 gleich 4*(10 hoch 0) + 3*
(10 hoch 1) + 2*(10 hoch 2) + 1*(10 hoch 3) ist (jede Zahl hoch 0 ist übrigens 1, nur nicht 0
hoch 0, da weiss man es nicht so genau!). Binärzahlen werden in Paketen zu je acht (als Byte
bezeichnet) oder 16 (als Wort bezeichnet) Binärziffern gehandhabt, weil die einzelnen Bits
kaum was wert sind.
● Hexadezimal: Hexadezimalzahlen sind eigentlich Viererpäckchen von Bits, denen man zur
Vereinfachung die Ziffern 0 bis 9 und A bis F (oder a bis f) gibt und als solche meistens
ASCII-verschlüsselt. A bis F deswegen, weil vier Bits Zahlen von 0 bis 15 sein können. So ist
binär 1010 soviel wie 1*(2 hoch 3) + 1*(2 hoch 1), also dezimal 10, kriegt dafür den
Buchstaben A. Der Buchstabe A liegt aber in der ASCII-Codetabelle beim dezimalen Wert 65,
als Kleinbuchstabe sogar bei 97. Das alles ist beim Umwandeln wichtig und beim Codieren zu
bedenken.

Soweit der Zahlenformatsalat. Die zum Umwandeln geschriebene Software soll einigermaßen
brauchbar für verschiedene Zwecke sein. Es lohnt sich daher, vor dem Schreiben und Verwenden ein
wenig Grütze zu investieren. Ich habe daher folgende Regeln ausgedacht und beim Schreiben
eingehalten:

● Binärzahlen: Alle Binärzahlen sind auf 16 Bit ausgelegt (Wertebereich 0..65.535). Sie sind in
den beiden Registern rBin1H (obere 8 Bit, MSB) und rBin1L (untere 8 Bit, LSB)
untergebracht. Dieses binäre Wort wird mit rBin1H:L abgekürzt. Bevorzugter Ort beim AVR
für die beiden ist z.B. R1 und R2, die Reihenfolge ist dabei egal. Für manche Umwandlungen
wird ein zweites binäres Registerpaar gebraucht, das hier als rBin2H:L bezeichnet wird. Es
kann z.B. in R3 und R4 gelegt werden. Es wird nach dem Gebrauch wieder in den
Normalzustand versetzt, deshalb kann es unbesehen auch noch für andere Zwecke dienen.
● BCD- und ASCII-Zahlen: Diese Zahlen werden generell mit dem Zeiger Z angesteuert
(Zeigerregister ZH:ZL oder R31:R30), weil solche Zahlen meistens irgendwo im SRAM-
Speicher herumstehen. Sie sind so angeordnet, dass die höherwertigste Ziffer die niedrigste
Adresse hat. Die Zahl 12345 würde also im SRAM so stehen: $0060: 1, $0061: 2, $0062: 3,
usw. Der Zeiger Z kann aber auch in den Bereich der Register gestellt werden, also z.B. auf
$0005. Dann läge die 1 in R5, die 2 in R6, die 3 in R7, usw. Die Software kann also die
Dezimalzahlen sowohl aus dem SRAM als auch aus den Registern verarbeiten. Aber Obacht:
es wird im Registerraum unbesehen alles überschrieben, was dort herumstehen könnte.
Sorgfältige Planung der Register ist dann heftig angesagt!
● Paketeinteilung: Weil man nicht immer alle Umwandlungsroutinen braucht, ist das
Gesamtpaket in vier Teilpakete eingeteilt. Die beiden letzten Pakete braucht man nur für
Hexzahlen, die beiden ersten zur Umrechnung von ASCII- oder BCD- zu Binär bzw. von
Binär in ASCII- und BCD. Jedes Paket ist mit den darin befindlichen Unterprogrammen
separat lauffähig, es braucht nicht alles eingebunden werden. Beim Entfernen von Teilen der
Pakete die Aufrufe untereinander beachten! Das Gesamtpaket umfasst 217 Worte Programm.
● Fehler: Tritt bei den Zahlenumwandlungen ein Fehler auf, dann wird bei allen
fehlerträchtigen Routinen das T-Flag gesetzt. Das kann mit BRTS oder BRTC bequem
abgefragt werden, um Fehler in der Zahl zu erkennen, abzufangen und zu behandeln. Wer das
T-Flag im Statusregister SREG noch für andere Zwecke braucht, muss alle "set"-, "clt"-,
"brts"- und "brtc"-Anweisungen auf ein anderes Bit in irgendeinem Register umkodieren. Bei
Fehlern bleibt der Zeiger Z einheitlich auf der Ziffer stehen, bei der der Fehler auftrat.
● Weiteres: Weitere Bedingungen gibt es im allgemeinen Teil des Quelltextes. Dort gibt es
auch einen Überblick zur Zahlenumwandlung, der alle Funktionen, Aufrufbedingungen und
Fehlerarten enthält.

Von ASCII nach Binär


Die Routine AscToBin2 eignet sich besonders gut für die Ermittlung von Zahlen aus Puffern. Sie
überliest beliebig viele führende Leerzeichen und Nullen und bricht die Zahlenumwandlung beim
ersten Zeichen ab, das keine gültige Dezimalziffer repräsentiert. Die Zahlenlänge muss deshalb nicht
vorher bekannt sein, der Zahlenwert darf nur den 16-Bit-Wertebereich der Binärzahl nicht
überschreiten. Auch dieser Fehler wird erkannt und mit dem T-Flag signalisiert.

Soll die Länge der Zahl exakt fünf Zeichen ASCII umfassen, kann die Routine Asc5ToBin2
verwendet werden. Hier wird jedes ungültige Zeichen, bis auf führende Nullen und Leerzeichen,
angemahnt.

Die Umrechnung erfolgt von links nach rechts, d.h. bei jeder weiteren Stelle der Zahl wird das
bisherige Ergebnis mit 10 multipliziert und die dazu kommende Stelle hinzugezählt. Das geht etwas
langsam, weil die Multiplikation mit 10 etwas rechenaufwendig ist. Es gibt sicher schnellere Arten
der Wandlung.

Von BCD zu Binär


Die Umwandlung von BCD zu Binär funktioniert ähnlich. Auf eine eingehende Beschreibung der
Eigenschaften dieses Quellcodes wird daher verzichtet.

Binärzahl mit 10 multiplizieren


Diese Routine Bin1Mul10 nimmt eine 16-Bit-Binärzahl mit 10 mal, indem sie diese kopiert und
durch Additionen vervielfacht. Aufwändig daran ist, dass praktisch bei jedem Addieren ein Überlauf
denkbar ist und abgefangen werden muss. Wer keine zu langen Zahlen zulässt oder wem es egal ist,
ob Unsinn rauskommt, kann die Branch-Anweisungen alle rauswerfen und das Verfahren damit
etwas beschleunigen.

Von binär nach ASCII


Die Wandlung von Binär nach ASCII erfolgt in der Routine Bin2ToAsc5. Das Ergebnis ist generell
fünfstellig. Die eigentliche Umwandlung erfolgt durch Aufruf von Bin2ToBcd5. Wie das
funktioniert, wird weiter unten beschrieben.

Wird statt Bin2ToAsc5 die Routine Bin2ToAsc aufgerufen, kriegt man den Zeiger Z auf die erste
Nicht-Null in der Zahl gesetzt und die Anzahl der Stellen im Register rBin2L zurück. Das ist
bequem, wenn man das Ergebnis über die serielle Schnittstelle senden will und unnötigen
Leerzeichen-Verkehr vermeiden will.

Von binär nach BCD


Bin2ToBcd5 rechnet die Binärzahl in rBin1H:L in dezimal um. Auch dieses Verfahren ist etwas
zeitaufwändig, aber sicher leicht zu verstehen. Die Umwandlung erfolgt durch fortgesetztes Abziehen
immer kleiner werdender Binärzahlen, die die dezimalen Stellen repräsentieren, also 10.000, 1.000,
100 und 10. Nur bei den Einern wird von diesem Schema abgewichen, hi.

Von binär nach Hex


Die Routine Bin2ToHex4 produziert aus der Binärzahl eine vierstellige Hex-ASCII-Zahl, die etwas
leichter zu lesen ist als das Original in binär. Oder mit welcher Wahrscheinlichkeit verschreiben Sie
sich beim Abtippen der Zahl 1011011001011110? Da ist B65E doch etwas bequemer und leichter zu
memorieren, fast so wie 46686 in dezimal.

Die Routine produziert die Hex-Ziffern A bis F in Großbuchstaben. Wer es lieber in a .. f mag: bitte
schön, Quelltext ändern.

Von Hex nach Binär


Mit Hex4ToBin2 geht es den umgekehrten Weg. Da hier das Problem der falschen Ziffern auftreten
kann, ist wieder jede Menge Fehlerbehandlungscode zusätzlich nötig.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/konversion.html1/20/2009 7:35:23 PM
Zahlenumwandlung in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Zahlenumwandlung => Quelltext

Quelltext der Zahlenumwandlungsroutinen


asm-Version dieses Quelltextes: konvert.asm

Allgemeine Bedingungen

; ********************************************************
; * Routinen zur Zahlumwandlung, Version 0.1 Januar 2002 *
; * (C)2002 by info!at!avr-asm-tutorial.net *
; ********************************************************
;
; Die folgenden Regeln gelten für alle Routinen zur Zahl-
; umwandlung:
; - Fehler während der Umwandlung werden durch ein gesetz-
; tes T-Bit im Status-Register signalisiert.
; - Der Z Zeiger zeigt entweder in das SRAM (Adresse >=
; $0060) oder auf einen Registerbereich (Adressen $0000
; bis $001D), die Register R0, R16 und R30/31 dürfen
; nicht in dem benutzten Bereich liegen!
; - ASCII- und BCD-kodierte mehrstellige Zahlen sind ab-
; steigend geordnet, d.h. die höherwertigen Ziffern ha-
; ben die niedrigerwertigen Adressen.
; - 16-bit-Binärzahlen sind generell in den Registern
; rBin1H:rBin1L lokalisiert, bei einigen Routinen wird
; zusätzlich rBin2H:rBin2L verwendet. Diese müssen im
; Hauptprogramm definiert werden.
; - Bei Binärzahlen ist die Lage im Registerbereich nicht
; maßgebend, sie können auf- oder absteigend geordnet
; sein oder getrennt im Registerraum liegen. Zu vernei-
; den ist eine Zuordnung zu R0, rmp, ZH oder ZL.
; - Register rmp (Bereich: R16..R29) wird innerhalb der
; Rechenroutinen benutzt, sein Inhalt ist nach Rückkehr
; nicht definiert.
; - Das Registerpaar Z wird innerhalb von Routinen verwen-
; det. Bei der Rückkehr ist sein Inhalt abhängig vom
; Fehlerstatus definiert.
; - Einige Routinen verwenden zeitweise Register R0. Sein
; Inhalt wird vor der Rückkehr wieder hergestellt.
; - Wegen der Verwendung des Z-Registers ist in jedem Fall
; die Headerdatei des Prozessors einzubinden oder ZL
; (R30) und ZH (R31) sind manuell zu definieren. Wird
; die Headerdatei oder die manuelle Definition nicht
; vorgenommen, gibt es beim Assemblieren eine Fehlermel-
; dung oder es geschehen rätselhafte Dinge.
; - Wegen der Verwendung von Unterroutinen muss der Sta-
; pelzeiger (SPH:SPL bzw. SPL bei mehr als 256 Byte SRAM)
; initiiert sein.

Überblick zur Zahlenumwandlung

;
; ************* Überblick über die Routinen **************
; Routine Aufruf Bedingungen Rückkehr,
; Fehler
; --------------------------------------------------------
; AscToBin2 Z zeigt auf Beendet beim ersten 16-bit-Bin
; erstes Zeichen, das nicht rBin1H:L,
; ASCII- einer Dezimalziffer Überlauf-
; Zeichen entspricht, über- fehler
; liest Leerzeichen
; und führende Nullen
; Asc5ToBin2 Z zeigt auf Benötigt exakt 5 16-bit-Bin
; erstes gültige Ziffern, rBin1H:L,
; ASCII- überliest Leerzei- Überlauf
; Zeichen chen und Nullen oder ungül-
; tige Ziffern
; Bcd5ToBin2 Z zeigt auf Benötigt exakt 5 16-bit-Bin
; 5-stellige gültige Ziffern rBin1H:L
; BCD-Zahl Überlauf
; oder ungül-
; tige Ziffern
; Bin2ToBcd5 16-bit-Bin Z zeigt auf erste 5-digit-BCD
; in rBin1H:L BCD-Ziffer (auch ab Z, keine
; nach Rückkehr) Fehler
; Bin2ToHex4 16-bit-Bin Z zeigt auf erste 4-stellige
; in rBin1H:L Hex-ASCII-Stelle, Hex-Zahl ab
; Ausgabe A...F Z, keine
; Fehler
; Hex4ToBin2 4-digit-Hex Benötigt exakt vier 16-bit-Bin
; Z zeigt auf Stellen Hex-ASCII, rBin1H:L,
; erste Stelle akzeptiert A...F und ungültige
; a...f Hex-Ziffer
;
; ******************* Umwandlungscode ********************
;
; Paket I: Von ASCII bzw. BCD nach Binär
;

Von ASCII nach Binär

; AscToBin2
; =========
; wandelt eine ASCII-kodierte Zahl in eine 2-Byte-/16-Bit-
; Binärzahl um.
; Aufruf: Z zeigt auf erste Stelle der umzuwandelnden
; Zahl, die Umwandlung wird bei der ersten nicht dezima-
; len Ziffer beendet.
; Stellen: Zulässig sind alle Zahlen, die innerhalb des
; Wertebereiches von 16 Bit binär liegen (0..65535).
; Rückkehr: Gesetztes T-Flag im Statusregister zeigt Feh-
; ler an.
; T=0: Zahl in rBin1H:L ist gültig, Z zeigt auf erstes
; Zeichen, das keiner Dezimalziffer entsprach
; T=1: Überlauffehler (Zahl zu groß), rBin1H:L undefi-
; niert, Z zeigt auf Zeichen, bei dessen Verarbeitung
; der Fehler auftrat.
; Benötigte Register: rBin1H:L (Ergebnis), rBin2H:L (wieder
; hergestellt), rmp
; Benötigte Unterroutinen: Bin1Mul10
;
AscToBin2:
clr rBin1H ; Ergebnis auf Null setzen
clr rBin1L
clt ; Fehlerflagge zurücksetzen
AscToBin2a:
ld rmp,Z+ ; lese Zeichen
cpi rmp,' ' ; ignoriere führende Leerzeichen ...
breq AscToBin2a
cpi rmp,'0' ; ... und Nullen
breq AscToBin2a
AscToBin2b:
subi rmp,'0' ; Subtrahiere ASCII-Null
brcs AscToBin2d ; Ende der Zahl erkannt
cpi rmp,10 ; prüfe Ziffer
brcc AscToBin2d ; Ende der Umwandlung
rcall Bin1Mul10 ; Binärzahl mit 10 malnehmen
brts AscToBin2c ; Überlauf, gesetztes T-Flag
add rBin1L,rmp ; Addiere Ziffer zur Binärzahl
ld rmp,Z+ ; Lese schon mal nächstes Zeichen
brcc AscToBin2b ; Kein Überlauf ins MSB
inc rBin1H ; Überlauf ins nächste Byte
brne AscToBin2b ; Kein Überlauf ins nächste Byte
set ; Setze Überlauffehler-Flagge
AscToBin2c:
sbiw ZL,1 ; Überlauf trat bei letztem Zeichen auf
AscToBin2d:
ret ; fertig, Rückkehr

Fünfstellige ASCII-Zahl nach


Binär

;
; Asc5ToBin2
; ==========
; wandelt eine fünfstellige ASCII-kodierte Zahl in 2-Byte-
; Binärzahl um.
; Aufruf: Z zeigt auf erste Stelle der ASCII-kodierten
; Zahl, führende Leerzeichen und Nullen sind erlaubt.
; Stellen: Die Zahl muss exakt 5 gültige Stellen haben.
; Rückkehr: T-Flag zeigt Fehlerbedingung an:
; T=0: Binärzahl in rBin1H:L ist gültig, Z zeigt auf
; erste Stelle der ASCII-kodierten Zahl.
; T=1: Fehler bei der Umwandlung. Entweder war die Zahl
; zu groß (0..65535, Z zeigt auf die Ziffer, bei der
; der Überlauf auftrat) oder sie enthilt ein ungülti-
; ges Zeichen (Z zeigt auf das ungültige Zeichen).
; Benötigte Register: rBin1H:L (Ergebnis), R0 (wiederher-
; gestellt), rBin2H:L (wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin1Mul10
;
Asc5ToBin2:
push R0 ; R0 wird als Zähler verwendet, retten
ldi rmp,6 ; Fünf Ziffern, einer zu viel
mov R0,rmp ; in Zählerregister R0
clr rBin1H ; Ergebnis auf Null setzen
clr rBin1L
clt ; Fehlerflagge T-Bit zurücksetzen
Asc5ToBin2a:
dec R0 ; Alle Zeichen leer oder Null?
breq Asc5ToBin2d ; Ja, beenden
ld rmp,Z+ ; Lese nächstes Zeichen
cpi rmp,' ' ; überlese Leerzeichen
breq Asc5ToBin2a ; geh zum nächsten Zeichen
cpi rmp,'0' ; überlese führende Nullen
breq Asc5ToBin2a ; geh zum nächsten Zeichen
Asc5ToBin2b:
subi rmp,'0' ; Behandle Ziffer, ziehe ASCII-0 ab
brcs Asc5ToBin2e ; Ziffer ist ungültig, raus
cpi rmp,10 ; Ziffer größer als neun?
brcc Asc5ToBin2e ; Ziffer ist ungültig, raus
rcall Bin1Mul10 ; Multipliziere Binärzahl mit 10
brts Asc5ToBin2e ; Überlauf, raus
add rBin1L,rmp ; addiere die Ziffer zur Binärzahl
ld rmp,z+ ; lese schon mal das nächste Zeichen
brcc Asc5ToBin2c ; Kein Überlauf in das nächste Byte
inc rBin1H ; Überlauf in das nächste Byte
breq Asc5ToBin2e ; Überlauf auch ins übernächste Byte
Asc5ToBin2c:
dec R0 ; Verringere Zähler für Anzahl Zeichen
brne Asc5ToBin2b ; Wandle weitere Zeichen um
Asc5ToBin2d: ; Ende der ASCII-kodierten Zahl erreicht
sbiw ZL,5 ; Stelle die Startposition in Z wieder her
pop R0 ; Stelle Register R0 wieder her
ret ; Kehre zurück
Asc5ToBin2e: ; Letztes Zeichen war ungültig
sbiw ZL,1 ; Zeige mit Z auf ungültiges Zeichen
pop R0 ; Stelle Register R0 wieder her
set ; Setze T-Flag für Fehler
ret ; und kejre zurück
;

Von BCD zu Binär

; Bcd5ToBin2
; ==========
; wandelt eine 5-bit-BCD-Zahl in eine 16-Bit-Binärzahl um
; Aufruf: Z zeigt auf erste Stelle der BCD-kodierten
; Zahl
; Stellen: Die Zahl muss exakt 5 gültige Stellen haben.
; Rückkehr: T-Flag zeigt Fehlerbedingung an:
; T=0: Binärzahl in rBin1H:L ist gültig, Z zeigt auf
; erste Stelle der BCD-kodierten Zahl.
; T=1: Fehler bei der Umwandlung. Entweder war die Zahl
; zu groß (0..65535, Z zeigt auf die Ziffer, bei der
; der Überlauf auftrat) oder sie enthielt ein ungülti-
; ges Zeichen (Z zeigt auf das ungültige Zeichen).
; Benötigte Register: rBin1H:L (Ergebnis), R0 (wiederher-
; gestellt), rBin2H:L (wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin1Mul10
;
Bcd5ToBin2:
push R0 ; Rette Register R0
clr rBin1H ; Setze Ergebnis Null
clr rBin1L
ldi rmp,5 ; Setze Zähler auf 5 Ziffern
mov R0,rmp ; R0 ist Zähler
clt ; Setze Fehlerflagge zurück
Bcd5ToBin2a:
ld rmp,Z+ ; Lese BCD-Ziffer
cpi rmp,10 ; prüfe ob Ziffer korrekt
brcc Bcd5ToBin2c ; ungültige BCD-Ziffer
rcall Bin1Mul10 ; Multipliziere Ergebnis mit 10
brts Bcd5ToBin2c ; Überlauf aufgetreten
add rBin1L,rmp ; Addiere Ziffer
brcc Bcd5ToBin2b ; Kein Überlauf ins nächste Byte
inc rBin1H ; Überlauf ins nächste Byte
breq Bcd5ToBin2c ; Überlauf ins übernächste Byte
Bcd5ToBin2b:
dec R0 ; weitere Ziffer?
brne Bcd5ToBin2a ; Ja
pop R0 ; Stelle Register wieder her
sbiw ZL,5 ; Setze Zeiger auf erste Stelle der BCD-Zahl
ret ; Kehre zurück
Bcd5ToBin2c:
sbiw ZL,1 ; Eine Ziffer zurück
pop R0 ; Stelle Register wieder her
set ; Setze T-flag, Fehler
ret ; Kehre zurück

Binärzahl mit 10 multiplizieren

;
; Bin1Mul10
; =========
; Multipliziert die 16-Bit-Binärzahl mit 10
; Unterroutine benutzt von AscToBin2, Asc5ToBin2, Bcd5ToBin2
; Aufruf: 16-Bit-Binärzahl in rBin1H:L
; Rückkehr: T-Flag zeigt gültiges Ergebnis an.
; T=0: rBin1H:L enthält gültiges Ergebnis.
; T=1: Überlauf bei der Multiplikation, rBin1H:L undefiniert
; Benutzte Register: rBin1H:L (Ergebnis), rBin2H:L (wird wieder
; hergestellt)
;
Bin1Mul10:
push rBin2H ; Rette die Register rBin2H:L
push rBin2L
mov rBin2H,rBin1H ; Kopiere die Zahl dort hin
mov rBin2L,rBin1L
add rBin1L,rBin1L ; Multipliziere Zahl mit 2
adc rBin1H,rBin1H
brcs Bin1Mul10b ; Überlauf, raus hier!
Bin1Mul10a:
add rBin1L,rbin1L ; Noch mal mit 2 malnehmen (=4*Zahl)
adc rBin1H,rBin1H
brcs Bin1Mul10b ; Überlauf, raus hier!
add rBin1L,rBin2L ; Addiere die Kopie (=5*Zahl)
adc rBin1H,rBin2H
brcs Bin1Mul10b ;Überlauf, raus hier!
add rBin1L,rBin1L ; Noch mal mit 2 malnehmen (=10*Zahl)
adc rBin1H,rBin1H
brcc Bin1Mul10c ; Kein Überlauf, überspringe
Bin1Mul10b:
set ; Überlauf, setze T-Flag
Bin1Mul10c:
pop rBin2L ; Stelle die geretteten Register wieder her
pop rBin2H
ret ; Kehre zurück
;
; ************************************************
;
; Paket II: Von Binär nach ASCII bzw. BCD
;

Von binär nach ASCII

; Bin2ToAsc5
; ==========
; wandelt eine 16-Bit-Binärzahl in eine fünfstellige ASCII-
; kodierte Dezimalzahl um
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf Anfang
; der Zahl
; Rückkehr: Z zeigt auf Anfang der Zahl, führende Nullen sind
; mit Leerzeichen überschrieben
; Benutzte Register: rBin1H:L (bleibt erhalten), rBin2H:L
; (wird überschrieben), rmp
; Aufgerufene Unterroutinen: Bin2ToBcd5
;
Bin2ToAsc5:
rcall Bin2ToBcd5 ; wandle Binärzahl in BCD um
ldi rmp,4 ; Zähler auf 4
mov rBin2L,rmp
Bin2ToAsc5a:
ld rmp,z ; Lese eine BCD-Ziffer
tst rmp ; prüfe ob Null
brne Bin2ToAsc5b ; Nein, erste Ziffer ungleich 0 gefunden
ldi rmp,' ' ; mit Leerzeichen überschreiben
st z+,rmp ; und ablegen
dec rBin2L ; Zähler um eins senken
brne Bin2ToAsc5a ; weitere führende Leerzeichen
ld rmp,z ; Lese das letzte Zeichen
Bin2ToAsc5b:
inc rBin2L ; Ein Zeichen mehr
Bin2ToAsc5c:
subi rmp,-'0' ; Addiere ASCII-0
st z+,rmp ; und speichere ab, erhöhe Zeiger
ld rmp,z ; nächstes Zeichen lesen
dec rBin2L ; noch Zeichen behandeln?
brne Bin2ToAsc5c ; ja, weitermachen
sbiw ZL,5 ; Zeiger an Anfang
ret ; fertig

Binär in ASCII ohne führende


Leerzeichen

;
; Bin2ToAsc
; =========
; wandelt eine 16-Bit-Binärzahl in eine fünfstellige ASCII-
; kodierte Dezimalzahl um, Zeiger zeigt auf die erste signi-
; fikante Ziffer der Zahl, und gibt Anzahl der Ziffern zu-
; rück
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf Anfang
; der Zahl (5 Stellen erforderlich, auch bei kleineren Zah-
; len!)
; Rückkehr: Z zeigt auf erste signifikante Ziffer der ASCII-
; kodierten Zahl, rBin2L enthält Länge der Zahl (1..5)
; Benutzte Register: rBin1H:L (bleibt erhalten), rBin2H:L
; (wird überschrieben), rmp
; Aufgerufene Unterroutinen: Bin2ToBcd5, Bin2ToAsc5
;
Bin2ToAsc:
rcall Bin2ToAsc5 ; Wandle Binärzahl in ASCII
ldi rmp,6 ; Zähler auf 6
mov rBin2L,rmp
Bin2ToAsca:
dec rBin2L ; verringere Zähler
ld rmp,z+ ; Lese Zeichen und erhöhe Zeiger
cpi rmp,' ' ; war Leerzeichen?
breq Bin2ToAsca ; Nein, war nicht
sbiw ZL,1 ; ein Zeichen rückwärts
ret ; fertig

Von binär nach BCD

;
; Bin2ToBcd5
; ==========
; wandelt 16-Bit-Binärzahl in 5-stellige BCD-Zahl um
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf die
; erste Stelle der BCD-kodierten Resultats
; Stellen: Die BCD-Zahl hat exakt 5 gültige Stellen.
; Rückkehr: Z zeigt auf die höchste BCD-Stelle
; Benötigte Register: rBin1H:L (wird erhalten), rBin2H:L
; (wird nicht wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin2ToDigit
;
Bin2ToBcd5:
push rBin1H ; Rette Inhalt der Register rBin1H:L
push rBin1L
ldi rmp,HIGH(10000) ; Lade 10.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 5.Stelle durch Abziehen
ldi rmp,HIGH(1000) ; Lade 1.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(1000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 4.Stelle durch Abziehen
ldi rmp,HIGH(100) ; Lade 100 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(100)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 3.Stelle durch Abziehen
ldi rmp,HIGH(10) ; Lade 10 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 2.Stelle durch Abziehen
st z,rBin1L ; Rest sind Einer
sbiw ZL,4 ; Setze Zeiger Z auf 5.Stelle (erste Ziffer)
pop rBin1L ; Stelle den Originalwert wieder her
pop rBin1H
ret ; und kehre zurück
;
; Bin2ToDigit
; ===========
; ermittelt eine dezimale Ziffer durch fortgesetztes Abziehen
; einer binär kodierten Dezimalstelle
; Unterroutine benutzt von: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc
; Aufruf: Binärzahl in rBin1H:L, binär kodierte Dezimalzahl
; in rBin2H:L, Z zeigt auf bearbeitete BCD-Ziffer
; Rückkehr: Ergebis in Z (bei Aufruf), Z um eine Stelle er-
; höht, keine Fehlerbehandlung
; Benutzte Register: rBin1H:L (enthält Rest der Binärzahl),
; rBin2H (bleibt erhalten), rmp
; Aufgerufene Unterroutinen: -
;
Bin2ToDigit:
clr rmp ; Zähler auf Null
Bin2ToDigita:
cp rBin1H,rBin2H ; Vergleiche MSBs miteinander
brcs Bin2ToDigitc ; MSB Binärzahl kleiner, fertig
brne Bin2ToDigitb ; MSB Binärzahl größer, subtrahiere
cp rBin1L,rBin2L ; MSB gleich, vergleiche LSBs
brcs Bin2ToDigitc ; LSB Binärzahl kleiner, fertig
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtrahiere LSB Dezimalzahl
sbc rBin1H,rBin2H ; Subtrahiere Carry und MSB
inc rmp ; Erhöhe den Zähler
rjmp Bin2ToDigita ; Weiter vergleichen/subtrahieren
Bin2ToDigitc:
st z+,rmp ; Speichere das Ergebnis und erhöhe Zeiger
ret ; zurück
;
; ***********************************************
;
; Paket III: Von Binär nach Hex-ASCII
;

Von binär nach Hex

; Bin2ToHex4
; ==========
; wandelt eine 16-Bit-Binärzahl in Hex-ASCII
; Aufruf: Binärzahl in rBin1H:L, Z zeigt auf erste Position
; des vierstelligen ASCII-Hex
; Rückkehr: Z zeigt auf erste Position des vierstelligen
; ASCII-Hex, ASCII-Ziffern A..F in Großbuchstaben
; Benutzte Register: rBin1H:L (bleibt erhalten), rmp
; Aufgerufene Unterroutinen: Bin1ToHex2, Bin1ToHex1
;
Bin2ToHex4:
mov rmp,rBin1H ; MSB in rmp kopieren
rcall Bin1ToHex2 ; in Hex-ASCII umwandeln
mov rmp,rBin1L ; LSB in rmp kopieren
rcall Bin1ToHex2 ; in Hex-ASCII umwandeln
sbiw ZL,4 ; Zeiger auf Anfang Hex-ASCII
ret ; fertig
;
; Bin1ToHex2 wandelt die 8-Bit-Binärzahl in rmp in Hex-ASCII
; gehört zu: Bin2ToHex4
;
Bin1ToHex2:
push rmp ; Rette Byte auf dem Stapel
swap rmp ; Vertausche die oberen und unteren 4 Bit
rcall Bin1ToHex1 ; wandle untere 4 Bits in Hex-ASCII
pop rmp ; Stelle das Byte wieder her
Bin1ToHex1:
andi rmp,$0F ; Maskiere die oberen vier Bits
subi rmp,-'0' ; Addiere ASCII-0
cpi rmp,'9'+1 ; Ziffern A..F?
brcs Bin1ToHex1a ; Nein
subi rmp,-7 ; Addiere 7 für A..F
Bin1ToHex1a:
st z+,rmp ; abspeichern und Zeiger erhöhen
ret ; fertig
;
; ***********************************************
;
; Paket IV: Von Hex-ASCII nach Binär
;

Von Hex nach Binär

; Hex4ToBin2
; ==========
; wandelt eine vierstellige Hex-ASCII-Zahl in eine 16-Bit-
; Binärzahl um
; Aufruf: Z zeigt auf die erste Stelle der Hex-ASCII-Zahl
; Rückkehr: T-Flag zeigt Fehler an:
; T=0: rBin1H:L enthält die 16-Bit-Binärzahl, Z zeigt
; auf die erste Hex-ASCII-Ziffer wie beim Aufruf
; T=1: ungültige Hex-ASCII-Ziffer, Z zeigt auf ungültige
; Ziffer
; Benutzte Register: rBin1H:L (enthält Ergebnis), R0 (wie-
; der hergestellt), rmp
; Aufgerufene Unterroutinen: Hex2ToBin1, Hex1ToBin1
;
Hex4ToBin2:
clt ; Lösche Fehlerflag
rcall Hex2ToBin1 ; Wandle zwei Hex-ASCII-Ziffern
brts Hex4ToBin2a ; Fehler, beende hier
mov rBin1H,rmp ; kopiere nach MSB Ergebnis
rcall Hex2ToBin1 ; Wandle zwei Hex-ASCII-Ziffern
brts Hex4ToBin2a ; Fehler, beende hier
mov rBin1L,rmp ; kopiere nach LSB Ergebnis
sbiw ZL,4 ; Ergebis ok, Zeiger auf Anfang
Hex4ToBin2a:
ret ; zurück
;
; Hex2ToBin1 wandelt 2-stellig-Hex-ASCII nach 8-Bit-Binär
;
Hex2ToBin1:
push R0 ; Rette Register R0
rcall Hex1ToBin1 ; Wandle nächstes Zeichen in Byte
brts Hex2ToBin1a ; Fehler, stop hier
swap rmp; untere vier Bits in obere vier Bits
mov R0,rmp ; zwischenspeichern
rcall Hex1ToBin1 ; Nächstes Zeichen umwandeln
brts Hex2ToBin1a ; Fehler, raus hier
or rmp,R0 ; untere und obere vier Bits zusammen
Hex2ToBin1a:
pop R0 ; Stelle R0 wieder her
ret ; zurück
;
; Hex1ToBin1 liest ein Zeichen und wandelt es in Binär um
;
Hex1ToBin1:
ld rmp,z+ ; Lese Zeichen
subi rmp,'0' ; Ziehe ASCII-0 ab
brcs Hex1ToBin1b ; Fehler, kleiner als 0
cpi rmp,10 ; A..F ; Ziffer größer als 9?
brcs Hex1ToBin1c ; nein, fertig
cpi rmp,$30 ; Kleinbuchstaben?
brcs Hex1ToBin1a ; Nein
subi rmp,$20 ; Klein- in Grossbuchstaben
Hex1ToBin1a:
subi rmp,7 ; Ziehe 7 ab, A..F ergibt $0A..$0F
cpi rmp,10 ; Ziffer kleiner $0A?
brcs Hex1ToBin1b ; Ja, Fehler
cpi rmp,16 ; Ziffer größer als $0F
brcs Hex1ToBin1c ; Nein, Ziffer in Ordnung
Hex1ToBin1b: ; Error
sbiw ZL,1 ; Ein Zeichen zurück
set ; Setze Fehlerflagge
Hex1ToBin1c:
ret ; Zurück

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/konvert.html1/20/2009 7:35:30 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/konvert.asm

; ********************************************************
; * Routinen zur Zahlumwandlung, Version 0.1 Januar 2002 *
; * (C)2002 by info@avr-asm-tutorial.net *
; ********************************************************
;
; Die folgenden Regeln gelten für alle Routinen zur Zahl-
; umwandlung:
; - Fehler während der Umwandlung werden durch ein gesetz-
; tes T-Bit im Status-Register signalisiert.
; - Der Z Zeiger zeigt entweder in das SRAM (Adresse >=
; $0060) oder auf einen Registerbereich (Adressen $0000
; bis $001D), die Register R0, R16 und R30/31 dürfen
; nicht in dem benutzten Bereich liegen!
; - ASCII- und BCD-kodierte mehrstellige Zahlen sind ab-
; steigend geordnet, d.h. die höherwertigen Ziffern ha-
; ben die niedrigerwertigen Adressen.
; - 16-bit-Binärzahlen sind generell in den Registern
; rBin1H:rBin1L lokalisiert, bei einigen Routinen wird
; zusätzlich rBin2H:rBin2L verwendet. Diese müssen im
; Hauptprogramm definiert werden.
; - Bei Binärzahlen ist die Lage im Registerbereich nicht
; maßgebend, sie können auf- oder absteigend geordnet
; sein oder getrennt im Registerraum liegen. Zu vernei-
; den ist eine Zuordnung zu R0, rmp, ZH oder ZL.
; - Register rmp (Bereich: R16..R29) wird innerhalb der
; Rechenroutinen benutzt, sein Inhalt ist nach Rückkehr
; nicht definiert.
; - Das Registerpaar Z wird innerhalb von Routinen verwen-
; det. Bei der Rückkehr ist sein Inhalt abhängig vom
; Fehlerstatus definiert.
; - Einige Routinen verwenden zeitweise Register R0. Sein
; Inhalt wird vor der Rückkehr wieder hergestellt.
; - Wegen der Verwendung des Z-Registers ist in jedem Fall
; die Headerdatei des Prozessors einzubinden oder ZL
; (R30) und ZH (R31) sind manuell zu definieren. Wird
; die Headerdatei oder die manuelle Definition nicht
; vorgenommen, gibt es beim Assemblieren eine Fehlermel-
; dung oder es geschehen rätselhafte Dinge.
; - Wegen der Verwendung von Unterroutinen muss der Sta-
; pelzeiger (SPH:SPL bzw. SPL bei <256 Byte SRAM)
; initiiert sein.
;
; ************* Überblick über die Routinen **************
; Routine Aufruf Bedingungen Rückkehr,
; Fehler
; --------------------------------------------------------
; AscToBin2 Z zeigt auf Beendet beim ersten 16-bit-Bin
; erstes Zeichen, das nicht rBin1H:L,
; ASCII- einer Dezimalziffer Überlauf-
; Zeichen entspricht, über- fehler
; liest Leerzeichen
; und führende Nullen
; Asc5ToBin2 Z zeigt auf Benötigt exakt 5 16-bit-Bin
; erstes gültige Ziffern, rBin1H:L,
; ASCII- überliest Leerzei- Überlauf
; Zeichen chen und Nullen oder ungül-
; tige Ziffern
; Bcd5ToBin2 Z zeigt auf Benötigt exakt 5 16-bit-Bin
; 5-stellige gültige Ziffern rBin1H:L
; BCD-Zahl Überlauf
; oder ungül-
; tige Ziffern
; Bin2ToBcd5 16-bit-Bin Z zeigt auf erste 5-digit-BCD
; in rBin1H:L BCD-Ziffer (auch ab Z, keine
; nach Rückkehr) Fehler
; Bin2ToHex4 16-bit-Bin Z zeigt auf erste 4-stellige
; in rBin1H:L Hex-ASCII-Stelle, Hex-Zahl ab
; Ausgabe A...F Z, keine
; Fehler
; Hex4ToBin2 4-digit-Hex Benötigt exakt vier 16-bit-Bin
; Z zeigt auf Stellen Hex-ASCII, rBin1H:L,
; erste Stelle akzeptiert A...F und ungültige
; a...f Hex-Ziffer
;
; ******************* Umwandlungscode ********************
;
; Paket I: Von ASCII bzw. BCD nach Binär
;
; AscToBin2
; =========
; wandelt eine ASCII-kodierte Zahl in eine 2-Byte-/16-Bit-
; Binärzahl um.
; Aufruf: Z zeigt auf erste Stelle der umzuwandelnden
; Zahl, die Umwandlung wird bei der ersten nicht dezima-
; len Ziffer beendet.
; Stellen: Zulässig sind alle Zahlen, die innerhalb des
; Wertebereiches von 16 Bit binär liegen (0..65535).
; Rückkehr: Gesetztes T-Flag im Statusregister zeigt Feh-
; ler an.
; T=0: Zahl in rBin1H:L ist gültig, Z zeigt auf erstes
; Zeichen, das keiner Dezimalziffer entsprach
; T=1: Überlauffehler (Zahl zu groß), rBin1H:L undefi-
; niert, Z zeigt auf Zeichen, bei dessen Verarbeitung
; der Fehler auftrat.
; Benötigte Register: rBin1H:L (Ergebnis), rBin2H:L (wieder
; hergestellt), rmp
; Benötigte Unterroutinen: Bin1Mul10
;
AscToBin2:
clr rBin1H ; Ergebnis auf Null setzen
clr rBin1L
clt ; Fehlerflagge zurücksetzen
AscToBin2a:
ld rmp,Z+ ; lese Zeichen
cpi rmp,' ' ; ignoriere führende Leerzeichen ...
breq AscToBin2a
cpi rmp,'0' ; ... und Nullen
breq AscToBin2a
AscToBin2b:
subi rmp,'0' ; Subtrahiere ASCII-Null
brcs AscToBin2d ; Ende der Zahl erkannt
cpi rmp,10 ; prüfe Ziffer
brcc AscToBin2d ; Ende der Umwandlung
rcall Bin1Mul10 ; Binärzahl mit 10 malnehmen
brts AscToBin2c ; Überlauf, gesetztes T-Flag
add rBin1L,rmp ; Addiere Ziffer zur Binärzahl
ld rmp,Z+ ; Lese schon mal nächstes Zeichen
brcc AscToBin2b ; Kein Überlauf ins MSB
inc rBin1H ; Überlauf ins nächste Byte
brne AscToBin2b ; Kein Überlauf ins nächste Byte
set ; Setze Überlauffehler-Flagge
AscToBin2c:
sbiw ZL,1 ; Überlauf trat bei letztem Zeichen auf
AscToBin2d:
ret ; fertig, Rückkehr
;
; Asc5ToBin2
; ==========
; wandelt eine fünfstellige ASCII-kodierte Zahl in 2-Byte-
; Binärzahl um.
; Aufruf: Z zeigt auf erste Stelle der ASCII-kodierten
; Zahl, führende Leerzeichen und Nullen sind erlaubt.
; Stellen: Die Zahl muss exakt 5 gültige Stellen haben.
; Rückkehr: T-Flag zeigt Fehlerbedingung an:
; T=0: Binärzahl in rBin1H:L ist gültig, Z zeigt auf
; erste Stelle der ASCII-kodierten Zahl.
; T=1: Fehler bei der Umwandlung. Entweder war die Zahl
; zu groß (0..65535, Z zeigt auf die Ziffer, bei der
; der Überlauf auftrat) oder sie enthilt ein ungülti-
; ges Zeichen (Z zeigt auf das ungültige Zeichen).
; Benötigte Register: rBin1H:L (Ergebnis), R0 (wiederher-
; gestellt), rBin2H:L (wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin1Mul10
;
Asc5ToBin2:
push R0 ; R0 wird als Zähler verwendet, retten
ldi rmp,6 ; Fünf Ziffern, einer zu viel
mov R0,rmp ; in Zählerregister R0
clr rBin1H ; Ergebnis auf Null setzen
clr rBin1L
clt ; Fehlerflagge T-Bit zurücksetzen
Asc5ToBin2a:
dec R0 ; Alle Zeichen leer oder Null?
breq Asc5ToBin2d ; Ja, beenden
ld rmp,Z+ ; Lese nächstes Zeichen
cpi rmp,' ' ; überlese Leerzeichen
breq Asc5ToBin2a ; geh zum nächsten Zeichen
cpi rmp,'0' ; überlese führende Nullen
breq Asc5ToBin2a ; geh zum nächsten Zeichen
Asc5ToBin2b:
subi rmp,'0' ; Behandle Ziffer, ziehe ASCII-0 ab
brcs Asc5ToBin2e ; Ziffer ist ungültig, raus
cpi rmp,10 ; Ziffer größer als neun?
brcc Asc5ToBin2e ; Ziffer ist ungültig, raus
rcall Bin1Mul10 ; Multipliziere Binärzahl mit 10
brts Asc5ToBin2e ; Überlauf, raus
add rBin1L,rmp ; addiere die Ziffer zur Binärzahl
ld rmp,z+ ; lese schon mal das nächste Zeichen
brcc Asc5ToBin2c ; Kein Überlauf in das nächste Byte
inc rBin1H ; Überlauf in das nächste Byte
breq Asc5ToBin2e ; Überlauf auch ins übernächste Byte
Asc5ToBin2c:
dec R0 ; Verringere Zähler für Anzahl Zeichen
brne Asc5ToBin2b ; Wandle weitere Zeichen um
Asc5ToBin2d: ; Ende der ASCII-kodierten Zahl erreicht
sbiw ZL,5 ; Stelle die Startposition in Z wieder her
pop R0 ; Stelle Register R0 wieder her
ret ; Kehre zurück
Asc5ToBin2e: ; Letztes Zeichen war ungültig
sbiw ZL,1 ; Zeige mit Z auf ungültiges Zeichen
pop R0 ; Stelle Register R0 wieder her
set ; Setze T-Flag für Fehler
ret ; und kejre zurück
;
; Bcd5ToBin2
; ==========
; wandelt eine 5-bit-BCD-Zahl in eine 16-Bit-Binärzahl um
; Aufruf: Z zeigt auf erste Stelle der BCD-kodierten
; Zahl
; Stellen: Die Zahl muss exakt 5 gültige Stellen haben.
; Rückkehr: T-Flag zeigt Fehlerbedingung an:
; T=0: Binärzahl in rBin1H:L ist gültig, Z zeigt auf
; erste Stelle der BCD-kodierten Zahl.
; T=1: Fehler bei der Umwandlung. Entweder war die Zahl
; zu groß (0..65535, Z zeigt auf die Ziffer, bei der
; der Überlauf auftrat) oder sie enthielt ein ungülti-
; ges Zeichen (Z zeigt auf das ungültige Zeichen).
; Benötigte Register: rBin1H:L (Ergebnis), R0 (wiederher-
; gestellt), rBin2H:L (wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin1Mul10
;
Bcd5ToBin2:
push R0 ; Rette Register R0
clr rBin1H ; Setze Ergebnis Null
clr rBin1L
ldi rmp,5 ; Setze Zähler auf 5 Ziffern
mov R0,rmp ; R0 ist Zähler
clt ; Setze Fehlerflagge zurück
Bcd5ToBin2a:
ld rmp,Z+ ; Lese BCD-Ziffer
cpi rmp,10 ; prüfe ob Ziffer korrekt
brcc Bcd5ToBin2c ; ungültige BCD-Ziffer
rcall Bin1Mul10 ; Multipliziere Ergebnis mit 10
brts Bcd5ToBin2c ; Überlauf aufgetreten
add rBin1L,rmp ; Addiere Ziffer
brcc Bcd5ToBin2b ; Kein Überlauf ins nächste Byte
inc rBin1H ; Überlauf ins nächste Byte
breq Bcd5ToBin2c ; Überlauf ins übernächste Byte
Bcd5ToBin2b:
dec R0 ; weitere Ziffer?
brne Bcd5ToBin2a ; Ja
pop R0 ; Stelle Register wieder her
sbiw ZL,5 ; Setze Zeiger auf erste Stelle der BCD-Zahl
ret ; Kehre zurück
Bcd5ToBin2c:
sbiw ZL,1 ; Eine Ziffer zurück
pop R0 ; Stelle Register wieder her
set ; Setze T-flag, Fehler
ret ; Kehre zurück
;
; Bin1Mul10
; =========
; Multipliziert die 16-Bit-Binärzahl mit 10
; Unterroutine benutzt von AscToBin2, Asc5ToBin2, Bcd5ToBin2
; Aufruf: 16-Bit-Binärzahl in rBin1H:L
; Rückkehr: T-Flag zeigt gültiges Ergebnis an.
; T=0: rBin1H:L enthält gültiges Ergebnis.
; T=1: Überlauf bei der Multiplikation, rBin1H:L undefiniert
; Benutzte Register: rBin1H:L (Ergebnis), rBin2H:L (wird wieder
; hergestellt)
;
Bin1Mul10:
push rBin2H ; Rette die Register rBin2H:L
push rBin2L
mov rBin2H,rBin1H ; Kopiere die Zahl dort hin
mov rBin2L,rBin1L
add rBin1L,rBin1L ; Multipliziere Zahl mit 2
adc rBin1H,rBin1H
brcs Bin1Mul10b ; Überlauf, raus hier!
Bin1Mul10a:
add rBin1L,rbin1L ; Noch mal mit 2 malnehmen (=4*Zahl)
adc rBin1H,rBin1H
brcs Bin1Mul10b ; Überlauf, raus hier!
add rBin1L,rBin2L ; Addiere die Kopie (=5*Zahl)
adc rBin1H,rBin2H
brcs Bin1Mul10b ;Überlauf, raus hier!
add rBin1L,rBin1L ; Noch mal mit 2 malnehmen (=10*Zahl)
adc rBin1H,rBin1H
brcc Bin1Mul10c ; Kein Überlauf, überspringe
Bin1Mul10b:
set ; Überlauf, setze T-Flag
Bin1Mul10c:
pop rBin2L ; Stelle die geretteten Register wieder her
pop rBin2H
ret ; Kehre zurück
;
; ************************************************
;
; Paket II: Von Binär nach ASCII bzw. BCD
;
; Bin2ToAsc5
; ==========
; wandelt eine 16-Bit-Binärzahl in eine fünfstellige ASCII-
; kodierte Dezimalzahl um
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf Anfang
; der Zahl
; Rückkehr: Z zeigt auf Anfang der Zahl, führende Nullen sind
; mit Leerzeichen überschrieben
; Benutzte Register: rBin1H:L (bleibt erhalten), rBin2H:L
; (wird überschrieben), rmp
; Aufgerufene Unterroutinen: Bin2ToBcd5
;
Bin2ToAsc5:
rcall Bin2ToBcd5 ; wandle Binärzahl in BCD um
ldi rmp,4 ; Zähler auf 4
mov rBin2L,rmp
Bin2ToAsc5a:
ld rmp,z ; Lese eine BCD-Ziffer
tst rmp ; prüfe ob Null
brne Bin2ToAsc5b ; Nein, erste Ziffer <> 0 gefunden
ldi rmp,' ' ; mit Leerzeichen überschreiben
st z+,rmp ; und ablegen
dec rBin2L ; Zähler um eins senken
brne Bin2ToAsc5a ; weitere führende Leerzeichen
ld rmp,z ; Lese das letzte Zeichen
Bin2ToAsc5b:
inc rBin2L ; Ein Zeichen mehr
Bin2ToAsc5c:
subi rmp,-'0' ; Addiere ASCII-0
st z+,rmp ; und speichere ab, erhöhe Zeiger
ld rmp,z ; nächstes Zeichen lesen
dec rBin2L ; noch Zeichen behandeln?
brne Bin2ToAsc5c ; ja, weitermachen
sbiw ZL,5 ; Zeiger an Anfang
ret ; fertig
;
; Bin2ToAsc
; =========
; wandelt eine 16-Bit-Binärzahl in eine fünfstellige ASCII-
; kodierte Dezimalzahl um, Zeiger zeigt auf die erste signi-
; fikante Ziffer der Zahl, und gibt Anzahl der Ziffern zu-
; rück
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf Anfang
; der Zahl (5 Stellen erforderlich, auch bei kleineren Zah-
; len!)
; Rückkehr: Z zeigt auf erste signifikante Ziffer der ASCII-
; kodierten Zahl, rBin2L enthält Länge der Zahl (1..5)
; Benutzte Register: rBin1H:L (bleibt erhalten), rBin2H:L
; (wird überschrieben), rmp
; Aufgerufene Unterroutinen: Bin2ToBcd5, Bin2ToAsc5
;
Bin2ToAsc:
rcall Bin2ToAsc5 ; Wandle Binärzahl in ASCII
ldi rmp,6 ; Zähler auf 6
mov rBin2L,rmp
Bin2ToAsca:
dec rBin2L ; verringere Zähler
ld rmp,z+ ; Lese Zeichen und erhöhe Zeiger
cpi rmp,' ' ; war Leerzeichen?
breq Bin2ToAsca ; Nein, war nicht
sbiw ZL,1 ; ein Zeichen rückwärts
ret ; fertig
;
; Bin2ToBcd5
; ==========
; wandelt 16-Bit-Binärzahl in 5-stellige BCD-Zahl um
; Aufruf: 16-Bit-Binärzahl in rBin1H:L, Z zeigt auf die
; erste Stelle der BCD-kodierten Resultats
; Stellen: Die BCD-Zahl hat exakt 5 gültige Stellen.
; Rückkehr: Z zeigt auf die höchste BCD-Stelle
; Benötigte Register: rBin1H:L (wird erhalten), rBin2H:L
; (wird nicht wieder hergestellt), rmp
; Aufgerufene Unterroutinen: Bin2ToDigit
;
Bin2ToBcd5:
push rBin1H ; Rette Inhalt der Register rBin1H:L
push rBin1L
ldi rmp,HIGH(10000) ; Lade 10.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 5.Stelle durch Abziehen
ldi rmp,HIGH(1000) ; Lade 1.000 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(1000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 4.Stelle durch Abziehen
ldi rmp,HIGH(100) ; Lade 100 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(100)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 3.Stelle durch Abziehen
ldi rmp,HIGH(10) ; Lade 10 in rBin2H:L
mov rBin2H,rmp
ldi rmp,LOW(10)
mov rBin2L,rmp
rcall Bin2ToDigit ; Ermittle 2.Stelle durch Abziehen
st z,rBin1L ; Rest sind Einer
sbiw ZL,4 ; Setze Zeiger Z auf 5.Stelle (erste Ziffer)
pop rBin1L ; Stelle den Originalwert wieder her
pop rBin1H
ret ; und kehre zurück
;
; Bin2ToDigit
; ===========
; ermittelt eine dezimale Ziffer durch fortgesetztes Abziehen
; einer binär kodierten Dezimalstelle
; Unterroutine benutzt von: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc
; Aufruf: Binärzahl in rBin1H:L, binär kodierte Dezimalzahl
; in rBin2H:L, Z zeigt auf bearbeitete BCD-Ziffer
; Rückkehr: Ergebis in Z (bei Aufruf), Z um eine Stelle er-
; höht, keine Fehlerbehandlung
; Benutzte Register: rBin1H:L (enthält Rest der Binärzahl),
; rBin2H (bleibt erhalten), rmp
; Aufgerufene Unterroutinen: -
;
Bin2ToDigit:
clr rmp ; Zähler auf Null
Bin2ToDigita:
cp rBin1H,rBin2H ; Vergleiche MSBs miteinander
brcs Bin2ToDigitc ; MSB Binärzahl kleiner, fertig
brne Bin2ToDigitb ; MSB Binärzahl größer, subtrahiere
cp rBin1L,rBin2L ; MSB gleich, vergleiche LSBs
brcs Bin2ToDigitc ; LSB Binärzahl kleiner, fertig
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtrahiere LSB Dezimalzahl
sbc rBin1H,rBin2H ; Subtrahiere Carry und MSB
inc rmp ; Erhöhe den Zähler
rjmp Bin2ToDigita ; Weiter vergleichen/subtrahieren
Bin2ToDigitc:
st z+,rmp ; Speichere das Ergebnis und erhöhe Zeiger
ret ; zurück
;
; ***********************************************
;
; Paket III: Von Binär nach Hex-ASCII
;
; Bin2ToHex4
; ==========
; wandelt eine 16-Bit-Binärzahl in Hex-ASCII
; Aufruf: Binärzahl in rBin1H:L, Z zeigt auf erste Position
; des vierstelligen ASCII-Hex
; Rückkehr: Z zeigt auf erste Position des vierstelligen
; ASCII-Hex, ASCII-Ziffern A..F in Großbuchstaben
; Benutzte Register: rBin1H:L (bleibt erhalten), rmp
; Aufgerufene Unterroutinen: Bin1ToHex2, Bin1ToHex1
;
Bin2ToHex4:
mov rmp,rBin1H ; MSB in rmp kopieren
rcall Bin1ToHex2 ; in Hex-ASCII umwandeln
mov rmp,rBin1L ; LSB in rmp kopieren
rcall Bin1ToHex2 ; in Hex-ASCII umwandeln
sbiw ZL,4 ; Zeiger auf Anfang Hex-ASCII
ret ; fertig
;
; Bin1ToHex2 wandelt die 8-Bit-Binärzahl in rmp in Hex-ASCII
; gehört zu: Bin2ToHex4
;
Bin1ToHex2:
push rmp ; Rette Byte auf dem Stapel
swap rmp ; Vertausche die oberen und unteren 4 Bit
rcall Bin1ToHex1 ; wandle untere 4 Bits in Hex-ASCII
pop rmp ; Stelle das Byte wieder her
Bin1ToHex1:
andi rmp,$0F ; Maskiere die oberen vier Bits
subi rmp,-'0' ; Addiere ASCII-0
cpi rmp,'9'+1 ; Ziffern A..F?
brcs Bin1ToHex1a ; Nein
subi rmp,-7 ; Addiere 7 für A..F
Bin1ToHex1a:
st z+,rmp ; abspeichern und Zeiger erhöhen
ret ; fertig
;
; ***********************************************
;
; Paket IV: Von Hex-ASCII nach Binär
;
; Hex4ToBin2
; ==========
; wandelt eine vierstellige Hex-ASCII-Zahl in eine 16-Bit-
; Binärzahl um
; Aufruf: Z zeigt auf die erste Stelle der Hex-ASCII-Zahl
; Rückkehr: T-Flag zeigt Fehler an:
; T=0: rBin1H:L enthält die 16-Bit-Binärzahl, Z zeigt
; auf die erste Hex-ASCII-Ziffer wie beim Aufruf
; T=1: ungültige Hex-ASCII-Ziffer, Z zeigt auf ungültige
; Ziffer
; Benutzte Register: rBin1H:L (enthält Ergebnis), R0 (wie-
; der hergestellt), rmp
; Aufgerufene Unterroutinen: Hex2ToBin1, Hex1ToBin1
;
Hex4ToBin2:
clt ; Lösche Fehlerflag
rcall Hex2ToBin1 ; Wandle zwei Hex-ASCII-Ziffern
brts Hex4ToBin2a ; Fehler, beende hier
mov rBin1H,rmp ; kopiere nach MSB Ergebnis
rcall Hex2ToBin1 ; Wandle zwei Hex-ASCII-Ziffern
brts Hex4ToBin2a ; Fehler, beende hier
mov rBin1L,rmp ; kopiere nach LSB Ergebnis
sbiw ZL,4 ; Ergebis ok, Zeiger auf Anfang
Hex4ToBin2a:
ret ; zurück
;
; Hex2ToBin1 wandelt 2-stellig-Hex-ASCII nach 8-Bit-Binär
;
Hex2ToBin1:
push R0 ; Rette Register R0
rcall Hex1ToBin1 ; Wandle nächstes Zeichen in Byte
brts Hex2ToBin1a ; Fehler, stop hier
swap rmp; untere vier Bits in obere vier Bits
mov R0,rmp ; zwischenspeichern
rcall Hex1ToBin1 ; Nächstes Zeichen umwandeln
brts Hex2ToBin1a ; Fehler, raus hier
or rmp,R0 ; untere und obere vier Bits zusammen
Hex2ToBin1a:
pop R0 ; Stelle R0 wieder her
ret ; zurück
;
; Hex1ToBin1 liest ein Zeichen und wandelt es in Binär um
;
Hex1ToBin1:
ld rmp,z+ ; Lese Zeichen
subi rmp,'0' ; Ziehe ASCII-0 ab
brcs Hex1ToBin1b ; Fehler, kleiner als 0
cpi rmp,10 ; A..F ; Ziffer größer als 9?
brcs Hex1ToBin1c ; nein, fertig
cpi rmp,$30 ; Kleinbuchstaben?
brcs Hex1ToBin1a ; Nein
subi rmp,$20 ; Klein- in Grossbuchstaben
Hex1ToBin1a:
subi rmp,7 ; Ziehe 7 ab, A..F ergibt $0A..$0F
cpi rmp,10 ; Ziffer kleiner $0A?
brcs Hex1ToBin1b ; Ja, Fehler
cpi rmp,16 ; Ziffer größer als $0F
brcs Hex1ToBin1c ; Nein, Ziffer in Ordnung
Hex1ToBin1b: ; Error
sbiw ZL,1 ; Ein Zeichen zurück
set ; Setze Fehlerflagge
Hex1ToBin1c:
ret ; Zurück

http://www.avr-asm-tutorial.net/avr_de/quellen/konvert.asm1/20/2009 7:35:32 PM
Binäre Fließkommazahlen in AVR Assembler

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Fließkomma

Umgang mit Festkommazahlen in


AVR Assembler
Sinn und Unsinn von Fließkommazahlen
Oberster Grundsatz: Verwende keine Fließkommazahlen, es sei denn, Du brauchst sie wirklich.
Fließkommazahlen sind beim AVR Ressourcenfresser, lahme Enten und brauchen wahnsinnige
Verarbeitungszeiten. So oder ähnlich geht es einem, der glaubt, Assembler sei schwierig und macht
lieber mit Basic und seinen höheren Genossen C und Pascal herum.
Nicht so in Assembler. Hier kriegst Du gezeigt, wie man bei 4 MHz Takt in gerade mal weniger als
60 Mikrosekunden, im günstigsten Fall in 18 Mikrosekunden, eine Multiplikation einer
Kommmazahl abziehen kann. Ohne extra Fließkommazahlen-Prozessor oder ähnlichem
Schnickschnack für Denkfaule.

Wie das geht? Zurück zu den Wurzeln! Die meisten Aufgaben mit Fließkommazahlen sind eigentlich
auch mit Festkommazahlen gut zu erledigen. Und die kann man nämlich mit einfachen Ganzzahlen
erledigen. Und die sind wiederum in Assembler leicht zu programmieren und sauschnell zu
verarbeiten. Das Komma denkt sich der Programmierer einfach dazu und schmuggelt es an einem
festem Platz einfach in die Strom von Ganzzahlen-Ziffern rein. Und keiner merkt, dass hier eigentlich
gemogelt wird.

Zum Seitenanfang

Lineare Umrechnungen
Als Beispiel folgende Aufgabe: ein 8-Bit-AD-Wandler misst ein Eingangssignal von 0,00 bis 2,55
Volt und liefert als Ergebnis eine Binärzahl zwischen $00 und $FF ab. Das Ergebnis, die Spannung,
soll aber als ASCII-Zeichenfolge auf einem LCD-Display angezeigt werden. Doofes Beispiel, weil es
so einfach ist: Die Hexzahl wird in eine BCD-kodierte Dezimalzahl zwischen 000 und 255
umgewandelt und nach der ersten Ziffer einfach das Komma eingeschmuggelt. Fertig.

Leider ist die Elektronikwelt manchmal nicht so einfach und stellt schwerere Aufgaben. Der AD-
Wandler tut uns nicht den Gefallen und liefert für Eingangsspannungen zwischen 0,00 und 5,00 Volt
die 8-Bit-Hexzahl $00 bis $FF. Jetzt stehen wir blöd da und wissen nicht weiter, weil wir die Hexzahl
eigentlich mit 500/255, also mit 1,9608 malnehmen müssten. Das ist eine doofe Zahl, weil sie fast
zwei ist, aber nicht so ganz. Und so ungenau wollten wir es halt doch nicht haben, wenn schon der
AD-Wandler mit einem Viertel Prozent Genauigkeit glänzt. Immerhin zwei Prozent Ungenauigkeit
beim höchsten Wert ist da doch zuviel des Guten.

Um uns aus der Affäre zu ziehen, multiplizieren wir das Ganze dann eben mit 500*256/255 oder
501,96 und teilen es anschließend wieder durch 256. Wenn wir jetzt anstelle 501,96 mit aufgerundet
502 multiplizieren (es lebe die Ganzzahl!), beträgt der Fehler noch ganze 0,008%. Mit dem können
wir einstweilen leben. Und das Teilen durch 256 ist dann auch ganz einfach, weil es eine bekannte
Potenz von Zwei ist, und weil der AVR sich beim Teilen durch Potenzen von Zwei so richtig
pudelwohl fühlt und abgeht wie Hund. Beim Teilen einer Ganzzahl durch 256 geht er noch schneller
ab, weil wir dann nämlich einfach das letzte Byte der Binärzahl weglassen können. Nix mit Schieben
und Rotieren wie beim richtigen Teilen.

Die Multiplikation einer 8-Bit-Zahl mit der 9-Bit-Zahl 502 (hex 01F6) kann natürlich ein Ergebnis
haben, das nicht mehr in 16 Bit passt. Hier müssen deshalb 3 Bytes oder 24 Bits für das Ergebnis
vorbereitet sein, damit nix überläuft. Während der Multiplikation der 8-Bit-Zahl wird die 9-Bit-Zahl
502 immer eine Stelle nach links geschoben (mit 2 multipliziert), passt also auch nicht mehr in 2
Bytes und braucht also auch drei Bytes. Damit erhalten wir als Beispiel folgende Belegung von
Registern beim Multiplizieren:
Zahl Wert (Beispiel) Register
Eingangswert 255 R1
Multiplikator 502 R4:R3:R2
Ergebnis 128.010 R7:R6:R5
Nach der Vorbelegung von R4:R3:R2 mit dem Wert 502 (Hex 00.01.F6) und dem Leeren der
Ergebnisregister R7:R6:R5 geht die Multiplikation jetzt nach folgendem Schema ab:

1. Testen, ob die Zahl schon Null ist. Wenn ja, sind wir fertig mit der Multiplikation.
2. Wenn nein, ein Bit aus der 8-Bit-Zahl nach rechts heraus in das Carry-Flag schieben und
gleichzeitig eine Null von links hereinschieben. Der Befehl heißt Logical-Shift-Right oder
LSR.
3. Wenn das herausgeschobene Bit im Carry eine Eins ist, wird der Inhalt des Multiplikators
(beim ersten Schritt 502) zum Ergebnis hinzu addiert. Beim Addieren auf Überläufe achten
(Addition von R5 mit R2 mit ADD, von R6 mit R3 sowie von R7 mit R4 mit ADC!). Ist es
eine Null, unterlassen wir das Addieren und gehen sofort zum nächsten Schritt.
4. Jetzt wird der Multiplikator mit zwei multipliziert, denn das nächste Bit der Zahl ist doppelt so
viel wert. Also R2 mit LSL links schieben (Bit 7 in das Carry herausschieben, eine Null in Bit
0 hineinschieben), dann das Carry mit ROL in R3 hineinrotieren (Bit 7 von R3 rutscht jetzt in
das Carry), und dieses Carry mit ROL in R4 rotieren.
5. Jetzt ist eine binäre Stelle der Zahl erledigt und es geht bei Schritt 1 weiter.

Das Ergebnis der Multiplikation mit 502 steht dann in den Ergebnisregistern R7:R6:R5. Wenn wir
jetzt das Register R5 ignorieren, steht in R7:R6 das Ergebnis der Division durch 256. Zur
Verbesserung der Genauigkeit können wir noch das Bit 7 von R5 dazu heranziehen, um die Zahl in
R7:R6 zu runden. Und unser Endergebnis in binärer Form braucht dann nur noch in dezimale ASCII-
Form umgewandelt werden (siehe Umwandlung binär zu Dezimal-ASCII). Setzen wir dem Ganzen
dann noch einen Schuss Komma an der richtigen Stelle zu, ist die Spannung fertig für die Anzeige im
Display.

Der gesamte Vorgang von der Ausgangszahl bis zum Endergebnis in ASCII dauert zwischen 79 und
228 Taktzyklen, je nachdem wieviel Nullen und Einsen die Ausgangszahl aufweist. Wer das mit der
Fließkommaroutine einer Hochsprache schlagen will, soll sich bei mir melden.

Zum Seitenanfang

Beispiel 1: 8-Bit-AD-Wandler mit Festkommaausgabe


Das bisher beschriebene Programm ist, noch ein wenig optimiert, in HTML-Form oder als Assembler-
Quelltext zugänglich. Der Quelltext enthält alle nötigen Routinen der Umrechnung in kompakter
Form, zum leichteren Import in andere Programme. Als Kopf ist ein Testabschnitt hinzugefügt, so
dass der Programmablauf im Studio simuliert werden kann.

Zum Seitenanfang

Beispiel 2: 10-Bit-AD-Wandler mit Festkommaausgabe


8-Bit-AD-Wandler sind selten, 10-Bit ist da schon gebräuchlicher. Weil 10 Bits noch etwas genauer
sind, dürfen es diesmal vier dezimale Stellen sein. Wobei die letzte dieser Stellen naturgemäß
klappert. Hier geht es zur HTML-Form und hier zum Assembler-Quelltext des Programmes.

Aufgrund des größeren Darstellungsbereichs braucht das Programm etwas mehr untere Register zum
Rumrechnen. Die Ausführungszeit ist etwas länger als mit 8 Bits und 3 Stellen, aber auch nicht
übermäßig.

Zum Seitenanfang

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/fpconv.html1/20/2009 7:35:34 PM
8-Bit-Binär zu 3-Digit-Dezimal-Festkommazahl

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Festkommazahl => 8-Bit-Wandlung

Assembler Quelltext der Umwandlung einer 8-


Bit-Zahl in eine dreistellige Festkommazahl
; Demonstriert Fließkomma-Umwandlung in
; Assembler, (C)2003 www.avr-asm-tutorial.net
;
; Die Aufgabe: Ein 8-Bit-Analog-Wandler-Signal
; in Binärform wird eingelesen, die Zahlen
; reichen von hex 00 bis FF.
; Diese Zahlen sind umzurechnen in eine
; Fließkommazahl zwischen 0,00 bis 5,00
; Volt.
;
; Der Programmablauf:
; 1. Multiplikation mit 502 (hex 01F6).
; Dieser Schritt multipliziert die Zahl mit
; den Faktoren 500 und 256 und dividiert
; mit 255 in einem Schritt.
; 2. Das Ergebnis wird gerundet und das letzte
; Byte abgeschnitten.
; Dieser Schritt dividiert durch 256, indem
; das letzte Byte des Ergebnisses ignoriert
; wird. Davor wird das Bit 7 des Ergebnisses
; abgefragt und zum Runden des Ergebnisses
; verwendet.
; 3. Die erhaltene Zahl wird in ASCII-Zeichen
; umgewandelt und mit einem Dezimalpunkt
; versehen.
; Das Ergebnis, eine Ganzzahl zwischen 0 und
; und 500 wird in eine Dezimalzahl verwan-
; delt und in der Form 5,00 als Fließkomma-
; zahl in ASCII-Zeichen dargestellt.
;
; Die verwendeten Register:
; Die Routinen benutzen die Register R8 bis R1,
; ohne diese vorher zu sichern. Zusätzlich wird
; das Vielzweckregister rmp verwendet, das in
; der oberen Registerhälfte liegen muss. Bitte
; beachten, dass diese verwendeten Register
; nicht mit anderen Verwendungen in Konflikt
; kommen können.
;
; Zu Beginn wird die 8-Bit-Zahl im Register
; R1 erwartet.
;
; Die Multiplikation verwendet R4:R3:R2 zur
; Speicherung des Multiplikators 502 (der
; bei der Berechnung maximal 8 mal links ge-
; schoben wird - Multiplikation mit 2). Das
; Ergebnis der Multiplikation wird in den Re-
; gistern R7:R6:R5 berechnet.
; Das Ergebnis der sogenannten Division durch
; 256 durch Ignorieren von R5 des Ergebnisses
; ist in R7:R6 gespeichert. Abhängig von Bit
; 7 in R5 wird zum Registerpaar R7:R6 eine
; Eins addiert. Das Ergebnis in R7:R6 wird
; in das Registerpaar R2:R1 kopiert.
; Die Umwandlung der Binärzahl in R2:R1 in
; eine ASCII-Zeichenfolge verwendet das Paar
; R4:R3 als Divisor für die Umwandlung. Das
; Ergebnis, der ASCII-String, ist in den Re-
; gistern R5:R6:R7:R8 abgelegt.
;
; Weitere Bedingungen:
; Die Umwandlung benutzt Unterprogramme, daher
; muss der Stapel funktionieren. Es werden
; maximal drei Ebenen Unterprogrammaufrufe
; verschachtelt (benötigt sechs Byte SRAM).
;
; Umwandlungszeiten:
; Die gesamte Umwandlung benötigt 228 Taktzyklen
; maximal (Umwandlung von $FF) bzw. 79 Takt-
; zyklen (Umwandlung von $00). Bei 4 MHz Takt
; entspricht dies 56,75 Mikrosekunden bzw. 17,75
; Mikrosekunden.
;
; Definitionen:
; Register
.DEF rmp = R16 ; als Vielzweckregister verwendet
;
; AVR-Typ
; Getestet für den Typ AT90S8515, die Angabe
; wird nur für den Stapel benötigt. Die Routinen
; arbeiten auf anderen AT90S-Prozessoren genauso
; gut.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start des Testprogramms
;
; Schreibt eine Zahl in R1 und startet die Wand-
; lungsroutine, nur für Testzwecke.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Richte den Stapel ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Wandle FF um
mov R1,rmp
rcall fpconv8 ; Rufe die Umwandlungsroutine
no_end: ; unendliche Schleife, wenn fertig
rjmp no_end
;
; Ablaufssteuerung der Umwandlungsroutine, ruft die
; verschiedenen Teilschritte auf
;
fpconv8:
rcall fpconv8m ; Multipliziere mit 502
rcall fpconv8r ; Runden und Division mit 256
rcall fpconv8a ; Umwandlung in ASCII-String
ldi rmp,'.' ; Setze Dezimalpunkt
mov R6,rmp
ret ; Alles fertig
;
; Unterprogramm Multiplikation mit 502
;
; Startbedingung:
; +--+
; |R1| Eingabezahl, im Beispiel $FF
; |FF|
; +--+
; +--+--+--+
; |R4|R3|R2| Multiplikant 502 = $00 01 F6
; |00|01|F6|
; +--+--+--+
; +--+--+--+
; |R7|R6|R5| Resultat, im Beispiel 128.010
; |01|F4|0A|
; +--+--+--+
;
fpconv8m:
clr R4 ; Setze den Multiplikant auf 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; leere Ergebnisregister
clr R6
clr R5
fpconv8m1:
or r1,R1 ; Prüfe ob noch Bits 1 sind
brne fpconv8m2 ; Noch Einsen, mach weiter
ret ; fertig, kehre zurück
fpconv8m2:
lsr R1 ; Schiebe Zahl nach rechts (teilen durch 2)
brcc fpconv8m3 ; Wenn das niedrigste Bit eine 0 war,
; dann überspringe den Additionsschritt
add R5,R2 ; Addiere die Zahl in R4:R3:R2 zum Ergebnis
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; Multipliziere R4:R3:R2 mit 2
rol R3
rol R4
rjmp fpconv8m1 ; Wiederhole für das nächste Bit
;
; Runde die Zahl in R7:R6 mit dem Wert von Bit 7 von R5
;
fpconv8r:
clr rmp ; Null nach rmp
lsl R5 ; Rotiere Bit 7 ins Carry
adc R6,rmp ; Addiere LSB mit Übertrag
adc R7,rmp ; Addiere MSB mit Übertrag
mov R2,R7 ; Kopiere den Wert nach R2:R1 (durch 256 teilen)
mov R1,R6
ret
;
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8
;
; +---+---+
; + R2| R1| Eingangswert 0..500
; +---+---+
; +---+---+
; | R4| R3| Dezimalteiler
; +---+---+
; +---+---+---+---+
; | R5| R6| R7| R8| Ergebnistext (für Eingangswert 500)
; |'5'|'.'|'0'|'0'|
; +---+---+---+---+
;
fpconv8a:
clr R4 ; Setze Dezimalteiler auf 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; Hole ASCII-Ziffer durch wiederholtes
Abziehen
mov R5,rmp ; Setze Hunderter Zeichen
ldi rmp,10 ; Setze Dezimalteiler auf 10
mov R3,rmp
rcall fpconv8d ; Hole die nächste Ziffer
mov R7,rmp
ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
add rmp,R1
mov R8,rmp ; Setze Einer Zeichen
ret
;
; Wandle Binärwort in R2:R1 in eine Dezimalziffer durch
fortgesetztes
; Abziehen des Dezimalteilers in R4:R3 (100, 10)
;
fpconv8d:
ldi rmp,'0' ; Beginne mit ASCII-0
fpconv8d1:
cp R1,R3 ; Vergleiche Wort mit Teiler
cpc R2,R4
brcc fpconv8d2 ; Carry nicht gesetzt, subtrahiere Teiler
ret ; fertig
fpconv8d2:
sub R1,R3 ; Subtrahiere Teilerwert
sbc R2,R4
inc rmp ; Ziffer um eins erhöhen
rjmp fpconv8d1 ; und noch einmal von vorne
;
; Ende der Fließkomma-Umwandlungsroutinen
;
;
; Ende des Umwandlungstestprogramms
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/fp_conv8_de.html1/20/2009 7:35:36 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/fp_conv8_de.asm

; Demonstriert Fließkomma-Umwandlung in
; Assembler, (C)2003 www.avr-asm-tutorial.net
;
; Die Aufgabe: Ein 8-Bit-Analog-Wandler-Signal
; in Binärform wird eingelesen, die Zahlen
; reichen von hex 00 bis FF.
; Diese Zahlen sind umzurechnen in eine
; Fließkommazahl zwischen 0,00 bis 5,00
; Volt.
;
; Der Programmablauf:
; 1. Multiplikation mit 502 (hex 01F6).
; Dieser Schritt multipliziert die Zahl mit
; den Faktoren 500 und 256 und dividiert
; mit 255 in einem Schritt.
; 2. Das Ergebnis wird gerundet und das letzte
; Byte abgeschnitten.
; Dieser Schritt dividiert durch 256, indem
; das letzte Byte des Ergebnisses ignoriert
; wird. Davor wird das Bit 7 des Ergebnisses
; abgefragt und zum Runden des Ergebnisses
; verwendet.
; 3. Die erhaltene Zahl wird in ASCII-Zeichen
; umgewandelt und mit einem Dezimalpunkt
; versehen.
; Das Ergebnis, eine Ganzzahl zwischen 0 und
; und 500 wird in eine Dezimalzahl verwan-
; delt und in der Form 5,00 als Fließkomma-
; zahl in ASCII-Zeichen dargestellt.
;
; Die verwendeten Register:
; Die Routinen benutzen die Register R8 bis R1,
; ohne diese vorher zu sichern. Zusätzlich wird
; das Vielzweckregister rmp verwendet, das in
; der oberen Registerhälfte liegen muss. Bitte
; beachten, dass diese verwendeten Register
; nicht mit anderen Verwendungen in Konflikt
; kommen können.
;
; Zu Beginn wird die 8-Bit-Zahl im Register
; R1 erwartet.
;
; Die Multiplikation verwendet R4:R3:R2 zur
; Speicherung des Multiplikators 502 (der
; bei der Berechnung maximal 8 mal links ge-
; schoben wird - Multiplikation mit 2). Das
; Ergebnis der Multiplikation wird in den Re-
; gistern R7:R6:R5 berechnet.
; Das Ergebnis der sogenannten Division durch
; 256 durch Ignorieren von R5 des Ergebnisses
; ist in R7:R6 gespeichert. Abhängig von Bit
; 7 in R5 wird zum Registerpaar R7:R6 eine
; Eins addiert. Das Ergebnis in R7:R6 wird
; in das Registerpaar R2:R1 kopiert.
; Die Umwandlung der Binärzahl in R2:R1 in
; eine ASCII-Zeichenfolge verwendet das Paar
; R4:R3 als Divisor für die Umwandlung. Das
; Ergebnis, der ASCII-String, ist in den Re-
; gistern R5:R6:R7:R8 abgelegt.
;
; Weitere Bedingungen:
; Die Umwandlung benutzt Unterprogramme, daher
; muss der Stapel funktionieren. Es werden
; maximal drei Ebenen Unterprogrammaufrufe
; verschachtelt (benötigt sechs Byte SRAM).
;
; Umwandlungszeiten:
; Die gesamte Umwandlung benötigt 228 Taktzyklen
; maximal (Umwandlung von $FF) bzw. 79 Takt-
; zyklen (Umwandlung von $00). Bei 4 MHz Takt
; entspricht dies 56,75 Mikrosekunden bzw. 17,75
; Mikrosekunden.
;
; Definitionen:
; Register
.DEF rmp = R16 ; als Vielzweckregister verwendet
;
; AVR-Typ
; Getestet für den Typ AT90S8515, die Angabe
; wird nur für den Stapel benötigt. Die Routinen
; arbeiten auf anderen AT90S-Prozessoren genauso
; gut.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start des Testprogramms
;
; Schreibt eine Zahl in R1 und startet die Wand-
; lungsroutine, nur für Testzwecke.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Richte den Stapel ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Wandle FF um
mov R1,rmp
rcall fpconv8 ; Rufe die Umwandlungsroutine
no_end: ; unendliche Schleife, wenn fertig
rjmp no_end
;
; Ablaufssteuerung der Umwandlungsroutine, ruft die
; verschiedenen Teilschritte auf
;
fpconv8:
rcall fpconv8m ; Multipliziere mit 502
rcall fpconv8r ; Runden und Division mit 256
rcall fpconv8a ; Umwandlung in ASCII-String
ldi rmp,'.' ; Setze Dezimalpunkt
mov R6,rmp
ret ; Alles fertig
;
; Unterprogramm Multiplikation mit 502
;
; Startbedingung:
; +--+
; |R1| Eingabezahl, im Beispiel $FF
; |FF|
; +--+
; +--+--+--+
; |R4|R3|R2| Multiplikant 502 = $00 01 F6
; |00|01|F6|
; +--+--+--+
; +--+--+--+
; |R7|R6|R5| Resultat, im Beispiel 128.010
; |01|F4|0A|
; +--+--+--+
;
fpconv8m:
clr R4 ; Setze den Multiplikant auf 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; leere Ergebnisregister
clr R6
clr R5
fpconv8m1:
or r1,R1 ; Prüfe ob noch Bits 1 sind
brne fpconv8m2 ; Noch Einsen, mach weiter
ret ; fertig, kehre zurück
fpconv8m2:
lsr R1 ; Schiebe Zahl nach rechts (teilen durch 2)
brcc fpconv8m3 ; Wenn das niedrigste Bit eine 0 war,
; dann überspringe den Additionsschritt
add R5,R2 ; Addiere die Zahl in R4:R3:R2 zum Ergebnis
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; Multipliziere R4:R3:R2 mit 2
rol R3
rol R4
rjmp fpconv8m1 ; Wiederhole für das nächste Bit
;
; Runde die Zahl in R7:R6 mit dem Wert von Bit 7 von R5
;
fpconv8r:
clr rmp ; Null nach rmp
lsl R5 ; Rotiere Bit 7 ins Carry
adc R6,rmp ; Addiere LSB mit Übertrag
adc R7,rmp ; Addiere MSB mit Übertrag
mov R2,R7 ; Kopiere den Wert nach R2:R1 (durch 256 teilen)
mov R1,R6
ret
;
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8
;
; +---+---+
; + R2| R1| Eingangswert 0..500
; +---+---+
; +---+---+
; | R4| R3| Dezimalteiler
; +---+---+
; +---+---+---+---+
; | R5| R6| R7| R8| Ergebnistext (für Eingangswert 500)
; |'5'|'.'|'0'|'0'|
; +---+---+---+---+
;
fpconv8a:
clr R4 ; Setze Dezimalteiler auf 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; Hole ASCII-Ziffer durch wiederholtes Abziehen
mov R5,rmp ; Setze Hunderter Zeichen
ldi rmp,10 ; Setze Dezimalteiler auf 10
mov R3,rmp
rcall fpconv8d ; Hole die nächste Ziffer
mov R7,rmp
ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
add rmp,R1
mov R8,rmp ; Setze Einer Zeichen
ret
;
; Wandle Binärwort in R2:R1 in eine Dezimalziffer durch fortgesetztes
; Abziehen des Dezimalteilers in R4:R3 (100, 10)
;
fpconv8d:
ldi rmp,'0' ; Beginne mit ASCII-0
fpconv8d1:
cp R1,R3 ; Vergleiche Wort mit Teiler
cpc R2,R4
brcc fpconv8d2 ; Carry nicht gesetzt, subtrahiere Teiler
ret ; fertig
fpconv8d2:
sub R1,R3 ; Subtrahiere Teilerwert
sbc R2,R4
inc rmp ; Ziffer um eins erhöhen
rjmp fpconv8d1 ; und noch einmal von vorne
;
; Ende der Fließkomma-Umwandlungsroutinen
;
;
; Ende des Umwandlungstestprogramms
;

http://www.avr-asm-tutorial.net/avr_de/quellen/fp_conv8_de.asm1/20/2009 7:35:37 PM
10-Bit-Binär zu 4-Digit-Dezimal-Festkommazahl

Pfad: Home => AVR-Übersicht => Binäres Rechnen => Festkommazahl => 10-Bit-Wandlung

Assembler Quelltext der Umwandlung einer 10-


Bit-Zahl in eine vierstellige Festkommazahl
; Demonstriert Fließkomma-Umwandlung in
; Assembler, (C)2003 www.avr-asm-tutorial.net
;
; Die Aufgabe: Ein 10-Bit-Analog-Wandler-Signal
; in Binärform wird eingelesen, die Zahlen
; reichen von hex 0000 bis 03FF.
; Diese Zahlen sind umzurechnen in eine
; Fließkommazahl zwischen 0,000 bis 5,000
; Volt.
;
; Der Programmablauf:
; 1. Die Eingabezahl wird geprüft, ob sie
; kleiner als $0400 ist.
; Das vermeidet Überläufe bei der anschlie-
; ßenden Multiplikation.
; 2. Multiplikation mit 320.313 (hex 04E338).
; Dieser Schritt multipliziert die Zahl mit
; den Faktoren 5.000 und 65.536 und divi-
; diert mit 1.023 in einem Schritt.
; 3. Das Ergebnis wird gerundet und die letzten
; beiden Bytes abgeschnitten.
; Dieser Schritt dividiert durch 65.536,
; indem die beiden letzten Bytes des Ergeb-
; nisses ignoriert werden. Davor wird das
; Bit 15 des Ergebnisse abgefragt und zum
; Runden des Ergebnisses verwendet.
; 4. Die erhaltene Zahl wird in ASCII-Zeichen
; umgewandelt und mit einem Dezimalpunkt
; versehen.
; Das Ergebnis, eine Zahl zwischen 0 und
; 5.000 wird in ASCII-Zeichen umgewandelt.
;
; Die verwendeten Register:
; Die Routinen benutzen die Register R10 bis R1,
; ohne diese vorher zu sichern. Zusätzlich wird
; das Vielzweckregister rmp verwendet, das in
; der oberen Registerhälfte liegen muss. Bitte
; beachten, dass diese verwendeten Register
; nicht mit anderen Verwendungen in Konflikt
; kommen können.
;
; Zu Beginn wird die 10-Bit-Zahl im Register-
; paar R2:R1 erwartet. Wenn die Zahl größer
; ist als $03FF, dann kehrt die Prüfroutine
; mit einem gesetzten Carry-Flag zurück und
; der Ergebnistext in R5:R6:R7:R8:R9:R10 wird
; auf den null-terminierten Ausdruck "E.EEEE"
; gesetzt.
; Die Multiplikation verwendet R6:R5:R4:R3 zur
; Speicherung des Multiplikators 320.313 (der
; bei der Berechnung maximal 10 mal links ge-
; schoben wird - Multiplikation mit 2). Das
; Ergebnis der Multiplikation wird in den Re-
; gistern R10:R9:R8:R7 berechnet.
; Das Ergebnis der sogenannten Division durch
; 65.536 durch Ignorieren von R8:R7 des Ergeb-
; nisses ist in R10:R9 gespeichert. Abhängig
; von Bit 7 in R8 wird zum Registerpaar R10:R9
; eine Eins addiert. Das Ergebnis in R10:R9
; wird in das Registerpaar R2:R1 kopiert.
; Die Umwandlung der Binärzahl in R2:R1 in
; eine ASCII-Zeichenfolge verwendet das Paar
; R4:R3 als Divisor für die Umwandlung. Das
; Ergebnis, der ASCII-String, ist in den Re-
; gistern R5:R6:R7:R8:R9:R10 (Null-terminiert)
; abgelegt.
;
; Weitere Bedingungen:
; Die Umwandlung benutzt Unterprogramme, daher
; muss der Stapel funktionieren. Es werden
; maximal drei Ebenen Unterprogrammaufrufe
; verschachtelt (benötigt sechs Byte SRAM).
;
; Umwandlungszeiten:
; Die gesamte Umwandlung benötigt 326 Taktzyklen
; maximal (Umwandlung von $03FF) bzw. 111 Takt-
; zyklen (Umwandlung von $0000). Bei 4 MHz Takt
; entspricht dies 81,25 Mikrosekunden bzw. 27,5
; Mikrosekunden.
;
; Definitionen:
; Register
.DEF rmp = R16 ; als Vielzweckregister verwendet
;
; AVR-Typ
; Getestet für den Typ AT90S8515, die Angabe
; wird nur für den Stapel benötigt. Die Routinen
; arbeiten auf anderen AT90S-Prozessoren genauso
; gut.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start des Testprogramms
;
; Schreibt eine Zahl in R2:R1 und startet die Wand-
; lungsroutine, nur für Testzwecke.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Richte den Stapel ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$03 ; Wandle $03FF um
mov R2,rmp
ldi rmp,$FF
mov R1,rmp
rcall fpconv10 ; Rufe die Umwandlungsroutine
no_end: ; unendliche Schleife, wenn fertig
rjmp no_end
;
; Ablaufssteuerung der Umwandlungsroutine, ruft die
; verschiedenen Teilschritte auf
;
fpconv10:
rcall fpconv10c ; Prüfe die Eingabezahl in R2:R1
brcs fpconv10e ; Wenn Carry, dann Ergebnis="E.EEE"
rcall fpconv10m ; Multipliziere mit 320.313
rcall fpconv10r ; Runden und Division mit 65536
rcall fpconv10a ; Umwandlung in ASCII-String
rjmp fpconv10f ; Setze Dezimalpunkt und Nullabschluss
fpconv10e:
ldi rmp,'E' ; Fehlermeldung in Ergebnistext
mov R5,rmp
mov R7,rmp
mov R8,rmp
mov R9, rmp
fpconv10f:
ldi rmp,'.' ; Setze Dezimalpunkt
mov R6,rmp
clr rmp ; Null-Abschluss setzen
mov R10,rmp
ret ; Alles fertig
;
; Unterprogramm Eingabeprüfung
;
fpconv10c:
ldi rmp,$03 ; Vergleiche MSB mit 03
cp rmp,R2 ; wenn R2>$03, setze carry bei Rückkehr
ret
;
; Unterprogramm Multiplikation mit 320.313
;
; Startbedingung:
; +---+---+
; | R2+ R1| Eingabezahl
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplikant 320.313 = $00 04 E3 38
; | 00| 04| E3| 38|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Resultat
; | 00| 00| 00| 00|
; +---+---+---+---+
;
fpconv10m:
clr R6 ; Setze den Multiplikant auf 320.313
ldi rmp,$04
mov R5,rmp
ldi rmp,$E3
mov R4,rmp
ldi rmp,$38
mov R3,rmp
clr R10 ; leere Ergebnisregister
clr R9
clr R8
clr R7
fpconv10m1:
mov rmp,R1 ; Prüfe ob noch Bits zu multiplizieren
or rmp,R2 ; Irgendein Bit Eins?
brne fpconv10m2 ; Noch Einsen, mach weiter
ret ; fertig, kehre zurück
fpconv10m2:
lsr R2 ; Schiebe MSB nach rechts (teilen durch 2)
ror R1 ; Rotiere LSB rechts und setze Bit 7
brcc fpconv10m3 ; Wenn das niedrigste Bit eine 0 war,
; dann überspringe den Additionsschritt
add R7,R3 ; Addiere die Zahl in R6:R5:R4:R3 zum Ergebnis
adc R8,R4
adc R9,R5
adc R10,R6
fpconv10m3:
lsl R3 ; Multipliziere R6:R5:R4:R3 mit 2
rol R4
rol R5
rol R6
rjmp fpconv10m1 ; Wiederhole für das nächste Bit
;
; Runde die Zahl in R10:R9 mit dem Wert von Bit 7 von R8
;
fpconv10r:
clr rmp ; Null nach rmp
lsl R8 ; Rotiere Bit 7 ins Carry
adc R9,rmp ; Addiere LSB mit Übertrag
adc R10,rmp ; Addiere MSB mit Übertrag
mov R2,R10 ; Kopiere den Wert nach R2:R1 (durch 65536
teilen)
mov R1,R9
ret
;
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8:R9:R10
;
; +---+---+
; + R2| R1| Eingangswert 0..5.000
; +---+---+
; +---+---+
; | R4| R3| Dezimalteiler
; +---+---+
; +---+---+---+---+---+---+
; | R5| R6| R7| R8| R9|R10| Ergebnistext (für Einmgangswert 5,000)
; |'5'|'.'|'0'|'0'|'0'|$00| mit Null-Abschluss
; +---+---+---+---+---+---+
;
fpconv10a:
ldi rmp,HIGH(1000) ; Setze Dezimalteiler auf 1.000
mov R4,rmp
ldi rmp,LOW(1000)
mov R3,rmp
rcall fpconv10d ; Hole ASCII-Ziffer durch wiederholtes
Abziehen
mov R5,rmp ; Setze Tausender Zeichen
clr R4 ; Setze Dezimalteiler auf 100
ldi rmp,100
mov R3,rmp
rcall fpconv10d ; Hole die nächste Ziffer
mov R7,rmp ; Setze Hunderter Zeichen
ldi rmp,10 ; Setze Dezimalteiler auf 10
mov R3,rmp
rcall fpconv10d ; Hole die nächste Ziffer
mov R8,rmp ; Setze Zehner Zeichen
ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
add rmp,R1
mov R9,rmp ; Setze Einer Zeichen
ret
;
; Wandle Binärwort in R2:R1 in eine Dezimalziffer durch
fortgesetztes
; Abziehen des Dezimalteilers in R4:R3 (1000, 100, 10)
;
fpconv10d:
ldi rmp,'0' ; Beginne mit ASCII-0
fpconv10d1:
cp R1,R3 ; Vergleiche Wort mit Teiler
cpc R2,R4
brcc fpconv10d2 ; Carry nicht gesetzt, subtrahiere Teiler
ret ; fertig
fpconv10d2:
sub R1,R3 ; Subtrahiere Teilerwert
sbc R2,R4
inc rmp ; Ziffer um eins erhöhen
rjmp fpconv10d1 ; und noch einmal von vorne
;
; Ende der Fließkomma-Umwandlungsroutinen
;
;
; Ende des Umwandlungstestprogramms
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/fp_conv10_de.html1/20/2009 7:35:39 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/fp_conv10_de.asm

; Demonstriert Fließkomma-Umwandlung in
; Assembler, (C)2003 www.avr-asm-tutorial.net
;
; Die Aufgabe: Ein 10-Bit-Analog-Wandler-Signal
; in Binärform wird eingelesen, die Zahlen
; reichen von hex 0000 bis 03FF.
; Diese Zahlen sind umzurechnen in eine
; Fließkommazahl zwischen 0,000 bis 5,000
; Volt.
;
; Der Programmablauf:
; 1. Die Eingabezahl wird geprüft, ob sie
; kleiner als $0400 ist.
; Das vermeidet Überläufe bei der anschlie-
; ßenden Multiplikation.
; 2. Multiplikation mit 320.313 (hex 04E338).
; Dieser Schritt multipliziert die Zahl mit
; den Faktoren 5.000 und 65.536 und divi-
; diert mit 1.023 in einem Schritt.
; 3. Das Ergebnis wird gerundet und die letzten
; beiden Bytes abgeschnitten.
; Dieser Schritt dividiert durch 65.536,
; indem die beiden letzten Bytes des Ergeb-
; nisses ignoriert werden. Davor wird das
; Bit 15 des Ergebnisse abgefragt und zum
; Runden des Ergebnisses verwendet.
; 4. Die erhaltene Zahl wird in ASCII-Zeichen
; umgewandelt und mit einem Dezimalpunkt
; versehen.
; Das Ergebnis, eine Zahl zwischen 0 und
; 5.000 wird in ASCII-Zeichen umgewandelt.
;
; Die verwendeten Register:
; Die Routinen benutzen die Register R10 bis R1,
; ohne diese vorher zu sichern. Zusätzlich wird
; das Vielzweckregister rmp verwendet, das in
; der oberen Registerhälfte liegen muss. Bitte
; beachten, dass diese verwendeten Register
; nicht mit anderen Verwendungen in Konflikt
; kommen können.
;
; Zu Beginn wird die 10-Bit-Zahl im Register-
; paar R2:R1 erwartet. Wenn die Zahl größer
; ist als $03FF, dann kehrt die Prüfroutine
; mit einem gesetzten Carry-Flag zurück und
; der Ergebnistext in R5:R6:R7:R8:R9:R10 wird
; auf den null-terminierten Ausdruck "E.EEEE"
; gesetzt.
; Die Multiplikation verwendet R6:R5:R4:R3 zur
; Speicherung des Multiplikators 320.313 (der
; bei der Berechnung maximal 10 mal links ge-
; schoben wird - Multiplikation mit 2). Das
; Ergebnis der Multiplikation wird in den Re-
; gistern R10:R9:R8:R7 berechnet.
; Das Ergebnis der sogenannten Division durch
; 65.536 durch Ignorieren von R8:R7 des Ergeb-
; nisses ist in R10:R9 gespeichert. Abhängig
; von Bit 7 in R8 wird zum Registerpaar R10:R9
; eine Eins addiert. Das Ergebnis in R10:R9
; wird in das Registerpaar R2:R1 kopiert.
; Die Umwandlung der Binärzahl in R2:R1 in
; eine ASCII-Zeichenfolge verwendet das Paar
; R4:R3 als Divisor für die Umwandlung. Das
; Ergebnis, der ASCII-String, ist in den Re-
; gistern R5:R6:R7:R8:R9:R10 (Null-terminiert)
; abgelegt.
;
; Weitere Bedingungen:
; Die Umwandlung benutzt Unterprogramme, daher
; muss der Stapel funktionieren. Es werden
; maximal drei Ebenen Unterprogrammaufrufe
; verschachtelt (benötigt sechs Byte SRAM).
;
; Umwandlungszeiten:
; Die gesamte Umwandlung benötigt 326 Taktzyklen
; maximal (Umwandlung von $03FF) bzw. 111 Takt-
; zyklen (Umwandlung von $0000). Bei 4 MHz Takt
; entspricht dies 81,25 Mikrosekunden bzw. 27,5
; Mikrosekunden.
;
; Definitionen:
; Register
.DEF rmp = R16 ; als Vielzweckregister verwendet
;
; AVR-Typ
; Getestet für den Typ AT90S8515, die Angabe
; wird nur für den Stapel benötigt. Die Routinen
; arbeiten auf anderen AT90S-Prozessoren genauso
; gut.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start des Testprogramms
;
; Schreibt eine Zahl in R2:R1 und startet die Wand-
; lungsroutine, nur für Testzwecke.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Richte den Stapel ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$03 ; Wandle $03FF um
mov R2,rmp
ldi rmp,$FF
mov R1,rmp
rcall fpconv10 ; Rufe die Umwandlungsroutine
no_end: ; unendliche Schleife, wenn fertig
rjmp no_end
;
; Ablaufssteuerung der Umwandlungsroutine, ruft die
; verschiedenen Teilschritte auf
;
fpconv10:
rcall fpconv10c ; Prüfe die Eingabezahl in R2:R1
brcs fpconv10e ; Wenn Carry, dann Ergebnis="E.EEE"
rcall fpconv10m ; Multipliziere mit 320.313
rcall fpconv10r ; Runden und Division mit 65536
rcall fpconv10a ; Umwandlung in ASCII-String
rjmp fpconv10f ; Setze Dezimalpunkt und Nullabschluss
fpconv10e:
ldi rmp,'E' ; Fehlermeldung in Ergebnistext
mov R5,rmp
mov R7,rmp
mov R8,rmp
mov R9, rmp
fpconv10f:
ldi rmp,'.' ; Setze Dezimalpunkt
mov R6,rmp
clr rmp ; Null-Abschluss setzen
mov R10,rmp
ret ; Alles fertig
;
; Unterprogramm Eingabeprüfung
;
fpconv10c:
ldi rmp,$03 ; Vergleiche MSB mit 03
cp rmp,R2 ; wenn R2>$03, setze carry bei Rückkehr
ret
;
; Unterprogramm Multiplikation mit 320.313
;
; Startbedingung:
; +---+---+
; | R2+ R1| Eingabezahl
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplikant 320.313 = $00 04 E3 38
; | 00| 04| E3| 38|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Resultat
; | 00| 00| 00| 00|
; +---+---+---+---+
;
fpconv10m:
clr R6 ; Setze den Multiplikant auf 320.313
ldi rmp,$04
mov R5,rmp
ldi rmp,$E3
mov R4,rmp
ldi rmp,$38
mov R3,rmp
clr R10 ; leere Ergebnisregister
clr R9
clr R8
clr R7
fpconv10m1:
mov rmp,R1 ; Prüfe ob noch Bits zu multiplizieren
or rmp,R2 ; Irgendein Bit Eins?
brne fpconv10m2 ; Noch Einsen, mach weiter
ret ; fertig, kehre zurück
fpconv10m2:
lsr R2 ; Schiebe MSB nach rechts (teilen durch 2)
ror R1 ; Rotiere LSB rechts und setze Bit 7
brcc fpconv10m3 ; Wenn das niedrigste Bit eine 0 war,
; dann überspringe den Additionsschritt
add R7,R3 ; Addiere die Zahl in R6:R5:R4:R3 zum Ergebnis
adc R8,R4
adc R9,R5
adc R10,R6
fpconv10m3:
lsl R3 ; Multipliziere R6:R5:R4:R3 mit 2
rol R4
rol R5
rol R6
rjmp fpconv10m1 ; Wiederhole für das nächste Bit
;
; Runde die Zahl in R10:R9 mit dem Wert von Bit 7 von R8
;
fpconv10r:
clr rmp ; Null nach rmp
lsl R8 ; Rotiere Bit 7 ins Carry
adc R9,rmp ; Addiere LSB mit Übertrag
adc R10,rmp ; Addiere MSB mit Übertrag
mov R2,R10 ; Kopiere den Wert nach R2:R1 (durch 65536 teilen)
mov R1,R9
ret
;
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8:R9:R10
;
; +---+---+
; + R2| R1| Eingangswert 0..5.000
; +---+---+
; +---+---+
; | R4| R3| Dezimalteiler
; +---+---+
; +---+---+---+---+---+---+
; | R5| R6| R7| R8| R9|R10| Ergebnistext (für Einmgangswert 5,000)
; |'5'|'.'|'0'|'0'|'0'|$00| mit Null-Abschluss
; +---+---+---+---+---+---+
;
fpconv10a:
ldi rmp,HIGH(1000) ; Setze Dezimalteiler auf 1.000
mov R4,rmp
ldi rmp,LOW(1000)
mov R3,rmp
rcall fpconv10d ; Hole ASCII-Ziffer durch wiederholtes Abziehen
mov R5,rmp ; Setze Tausender Zeichen
clr R4 ; Setze Dezimalteiler auf 100
ldi rmp,100
mov R3,rmp
rcall fpconv10d ; Hole die nächste Ziffer
mov R7,rmp ; Setze Hunderter Zeichen
ldi rmp,10 ; Setze Dezimalteiler auf 10
mov R3,rmp
rcall fpconv10d ; Hole die nächste Ziffer
mov R8,rmp ; Setze Zehner Zeichen
ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
add rmp,R1
mov R9,rmp ; Setze Einer Zeichen
ret
;
; Wandle Binärwort in R2:R1 in eine Dezimalziffer durch fortgesetztes
; Abziehen des Dezimalteilers in R4:R3 (1000, 100, 10)
;
fpconv10d:
ldi rmp,'0' ; Beginne mit ASCII-0
fpconv10d1:
cp R1,R3 ; Vergleiche Wort mit Teiler
cpc R2,R4
brcc fpconv10d2 ; Carry nicht gesetzt, subtrahiere Teiler
ret ; fertig
fpconv10d2:
sub R1,R3 ; Subtrahiere Teilerwert
sbc R2,R4
inc rmp ; Ziffer um eins erhöhen
rjmp fpconv10d1 ; und noch einmal von vorne
;
; Ende der Fließkomma-Umwandlungsroutinen
;
;
; Ende des Umwandlungstestprogramms
;

http://www.avr-asm-tutorial.net/avr_de/quellen/fp_conv10_de.asm1/20/2009 7:35:40 PM
Hardware Multiplikation in AVR Assembler

Path: Home => AVR-Überblick => Binäre Berechnungen => Hardware Multiplikation

Binäre Hardware Multiplikation in AVR


Assembler

Alle ATmega, AT90CAN and AT90PWM haben einen Multiplikator an Bord, der 8- mal 8-Bit-Multiplikationen in
nur zwei Taktzyklen durchführt. Wenn also Multiplikationen durchgeführt werden müssen und man sicher ist, dass die
Software niemals in einem AT90S- oder ATtiny-Prozessor laufen werden muss, sollte man diese schnelle Hardware-
Möglichkeit nutzen. Diese Seite zeigt, wie man das macht.
Es gibt hier folgende Abteilungen:

1. 8-mit-8-Bit-Zahlen
2. 16-mit-8-Bit-Zahlen
3. 16-mit-16-Bit-Zahlen
4. 16-mit-24-Bit-Zahlen

Hardware Multiplikation von 8-mal-8-Bit Binärzahlen


Diese Aufgabe ist einfach und direkt.
Wenn die zwei Binärzahlen in den
Registern R16 und R17 stehen, dann muss
man nur folgende Instruktion eingeben:

mul R16,R17

Weil das Ergebnis der Multiplikation bis


zu 16 Bit lange Zahlen ergibt, ist das Ergebnis in den Registern R1 (höherwertiges Byte) und R0 (niedrigerwertiges
Byte) untergebracht. Das war es auch schon.

Das Programm
demonstriert die Simulation
im Studio. Es multipliziert
dezimal 250 (hex FA) mit
dezimal 100 (hex 64) in
den Registern R16 und R17.

Die Register R0 (LSB) und R1 (MSB) enthalten das Ergebnis hex 61A8
oder dezimal 25,000.

Und: ja, die Multiplikation braucht bloß zwei Zyklen, oder 2


Mikrosekunden bei einem Takt von einem MHz.

Zum Seitenanfang

Hardware Multiplikation von 16- mit 8-Bit-Zahl


Sind größere Zahlen zu multiplizieren? Die Hardware ist auf 8 Bit beschränkt, also müssen wir ersatzweise einige
geniale Ideen anwenden. Das ist an diesem Beispiel 16 mal 8 gezeigt. Verstehen des Konzepts hilft bei der
Anwendung der Methode und es ist ein leichtes, das später auf die 32- mit 64-Bit-Multiplikation zu übertragen.

Zuerst die Mathematik: eine 16-Bit-Zahl


lässt sich in zwei 8-Bit-Zahlen auftrennen,
wobei die höherwertige der beiden Zahlen
mit dezimal 256 oder hex 100 mal
genommen wird. Für die, die eine
Erinnerung brauchen: die Dezimalzahl
1234 kann man auch als die Summe aus
(12*100) und 34 betrachten, oder auch als
die Summe aus (1*1000), (2*100), (2*10)
und 4. Die 16-Bit-Binärzahl m1 ist also gleich 256*m1M plus m1L, wobei m1M das MSB und m1L das LSB ist.
Multiplikation dieser Zahl mit der 8-Bit-Zahl m2 ist also mathematisch ausgedrückt:

m1 * m2 = (256*m1M + m1L) * m2 = 256*m1M*m2 + m1L*m2

Wir müssen also lediglich zwei Multiplikationen durchführen und die Ergebnisse addieren. Zwei Multiplikationen? Es
sind doch drei * zu sehen! Für die Multiplikation mit 256 braucht man in der Binärwelt keinen Hardware-
Multiplikator, weil es ausreicht, die Zahl einfach um ein Byte nach links zu rücken. Genauso wie in der Dezimalwelt
eine Multiplikation mit 10 einfach ein Linksrücken um eine Stelle ist und die frei werdende leere Ziffer mit Null
gefüllt wird.

Beginnen wir mit einem praktischen Beispiel. Zuerst brauchen wir einige Register, um

1. die Zahlen m1 und m2 zu laden,


2. für das Ergebnis Raum zu haben, das bis zu 24 Bit lang werden kann.

;
; Testet Hardware Multiplikation 16-mit-8-Bit
;
; Register Definitionen:
;
.def Res1 = R2 ; Byte 1 des Ergebnisses
.def Res2 = R3 ; Byte 2 des Ergebnisses
.def Res3 = R4 ; Byte 3 des Ergebnisses
.def m1L = R16 ; LSB der Zahl m1
.def m1M = R17 ; MSB der Zahl m1
.def m2 = R18 ; die Zahl m2

Zuerst werden die Zahlen in die Register geladen:

;
; Lade Register
;
.equ m1 = 10000
;
ldi m1M,HIGH(m1) ; obere 8 Bits von m1 in m1M
ldi m1L,LOW(m1) ; niedrigere 8 Bits von m1 in m1L
ldi m2,250 ; 8-Bit Konstante in m2

Die beiden Zahlen sind in R17:R16 (dez 10000 = hex 2710)


und R18 (dez 250 = hex FA) geladen.

Dann multiplizieren wir zuerst das niedrigerwertige Byte:

;
; Multiplikation
;
mul m1L,m2 ; Multipliziere LSB
mov Res1,R0 ; kopiere Ergebnis in Ergebnisregister
mov Res2,R1

Die LSB-Multiplikation von hex 27 mit hex FA ergibt hex


0F0A, das in die Register R0 (LSB, hex A0) und R1 (MSB,
hex 0F) geschrieben wurde. Das Ergebnis wird in die beiden
untersten Bytes der Ergebnisregister, R3:R2, kopiert.

Nun folgt die Multiplikation des MSB mit m2:

mul m1M,m2 ; Multiplizere MSB

Die Multiplikation des MSB von m1, hex 10, mit m2, hex
FA, ergibt hex 2616 in R1:R0.

Nun werden zwei Schritte auf einmal gemacht: die Multiplikation mit 256 und die Addition des Ergebnisses zum
bisherigen Ergebnis. Das wird erledigt durch Addition von R1:R0 zu Res3:Res2 anstelle von Res2:Res1. R1 wird
zunächst schlicht nach Res3 kopiert. Dann wird R0 zu Res2 addiert. Falls dabei das Übertragsflag Carry nach der
Addition gesetzt ist, muss noch das nächsthöre Byte Res3 um Eins erhöht werden.

mov Res3,R1 ; Kopiere MSB des Ergebnisses zum Ergebnis-Byte 3


add Res2,R0 ; Addiere LSB des Ergebnisses zum Ergebnis-Byte 2
brcc NoInc ; Wenn Carry nicht gesetzt, springe
inc Res3 ; erhoehe Ergebnis-Byte 3
NoInc:

Das Ergebnis in R4:R3:R2 ist hex 2625A9, was dezimal


2500000 entspricht (wie jeder sofort weiß), und das ist korrekt.

Der Zykluszähler zeigt nach der Multiplikation auf 10, bei 1


MHz Takt sind gerade mal 10 Mikrosekunden vergangen.
Sehr viel schneller als die Software-Multiplikation!

Zum Seitenanfang

Hardware Multiplikation einer 16- mit einer 16-bit-Binärzahl


Nun, da wir das Prinzip verstanden haben,
sollte es einfach sein die 16-mal-16-
Multiplikation zu erledigen. Das Ergebnis
benötigt jetzt vier Bytes (Res4:Res3:Res2:
Res1, untergebracht in R5:R4:R3:R2).
Die Formel lautet:

m1 * m2 = (256*m1M + m1L) *
(256*m2M + m2L)
= 65536*m1M*m2M + 256*m1M*m2L
+ 256*m1L*m2M + m1L*m2L

Offensichtlich sind jetzt vier Multiplikationen zu erledigen. Wir beginnen mit den beiden einfachsten, der ersten und
der letzten: ihre Ergebnisse können einfach in die Ergebnisregister kopiert werden. Die beiden mittleren
Multiplikationen in der Formel müssen zu den beiden mittleren Ergebnisregistern addiert werden. Mögliche Überläufe
müssen in das Ergebnisregister Res4 übertragen werden, wofür hier ein einfacher Trick angewendet wird, der einfach
zu verstehen sein dürfte. Die Software:

;
; Test Hardware Multiplikation 16 mal 16
;
; Definiere Register
;
.def Res1 = R2
.def Res2 = R3
.def Res3 = R4
.def Res4 = R5
.def m1L = R16
.def m1M = R17
.def m2L = R18
.def m2M = R19
.def tmp = R20
;
; Lade Startwerte
;
.equ m1 = 10000
.equ m2 = 25000
;
ldi m1M,HIGH(m1)
ldi m1L,LOW(m1)
ldi m2M,HIGH(m2)
ldi m2L,LOW(m2)
;
; Multipliziere
;
clr R20 ; leer, fuer Uebertraege
mul m1M,m2M ; Multipliziere MSBs
mov Res3,R0 ; Kopie in obere Ergebnisregister
mov Res4,R1
mul m1L,m2L ; Multipliziere LSBs
mov Res1,R0 ; Kopie in untere Ergebnisregister
mov Res2,R1
mul m1M,m2L ; Multipliziere 1M mit 2L
add Res2,R0 ; Addiere zum Ergebnis
adc Res3,R1
adc Res4,tmp ; Addiere Uebertrag
mul m1L,m2M ; Multipliziere 1L mit 2M
add Res2,R0 ; Addiere zum Ergebnis
adc Res3,R1
adc Res4,tmp
;
; Multiplikation fertig
;

Die Simulation im Studio zeigt die folgenden Schritte. Das Laden der beiden Konstanten 10000 (hex 2710) und 25000
(hex 61A8) in die Register im oberen Registerraum ...

Multiplikation der beiden MSBs (hex 27 und 61) und


kopieren des Ergebnisses in R1:R0 in die beiden oberen
Ergebnisregister R5:R4 (Multiplikation mit 65536
eingeschlossen) ...

Multiplikation der beiden LSBs (hex 10 und A8) und kopieren


des Ergebnisses in R1:R0 in die beiden niedrigeren
Ergebnisregister R3:R2 ...

Multiplikation des MSB von m1 mit dem LSB von m2, und
Addition des Ergebnisses in R1:R0 zu den beiden mittleren
Ergebnisregistern, kein Übertrag ist erfolgt ...

Multiplikation des LSB von m1 mit dem MSB von m2, sowie
Addition des Ergebnisses in R1:R0 mit den beiden mittleren
Ergebnisbytes, kein Übertrag. Das Ergebnis ist hex
0EE6B280, was dezimal 250000000 ist und offenbar korrekt ...

Die Multiplikation hat 19 Taktzyklen gebraucht, das ist sehr


viel schneller als die Software-Multiplikation. Ein weiterer
Vorteil: die benötigte Zeit ist IMMER genau 19 Taktzyklen
lang, nicht abhängig von den Zahlenwerten (wie es bei der
Software-Multiplikation der Fall ist) und vom Auftreten von
Überläufen (deshalb der Trick mit der Addition von Null mit
Carry). Darauf kann man sich verlassen ...

Zum Seitenanfang

4. Hardware Multiplikation einer 16- mit einer 24-Bit-Binärzahl


Die

Multiplikation einer 16-Bit-Binärzahl "a" mit einer 24-Bit-Binärzahl "b" führt im Ergebnis zu einem maximal 40 Bit
breiten Ergebnis. Das Multiplizier-Schema erfordert sechs 8-mit-8-Bit-Multiplikationen und das Addieren der
Ergebnisse an der richtigen Position zum Gesamtergebnis. Der Assembler-Code dafür:

; Hardware Multiplikation 16 mit 24 Bit


.include "m8def.inc"
;
; Register Definitionen
.def a1 = R2 ; definiere 16-bit Register
.def a2 = R3
.def b1 = R4 ; definiere 24-bit Register
.def b2 = R5
.def b3 = R6
.def e1 = R7 ; definiere 40-bit Ergebnisregister
.def e2 = R8
.def e3 = R9
.def e4 = R10
.def e5 = R11
.def c0 = R12 ; Hilfsregister fuer Additionen
.def rl = R16 ; Laderegister
;
; Load constants
.equ a = 10000 ; Multiplikator a, hex 2710
.equ b = 1000000 ; Multiplikator b, hex 0F4240
ldi rl,BYTE1(a) ; lade a
mov a1,rl
ldi rl,BYTE2(a)
mov a2,rl
ldi rl,BYTE1(b) ; lade b
mov b1,rl
ldi rl,BYTE2(b)
mov b2,rl
ldi rl,BYTE3(b)
mov b3,rl
;
; Loesche Registers
clr e1 ; Loesche Ergebnisregister
clr e2
clr e3
clr e4
clr e5
clr c0 ; loesche Hilfsregister
;
; Multipliziere
mul a2,b3 ; Term 1
add e4,R0 ; addiere zum Ergebnis
adc e5,R1
mul a2,b2 ; Term 2
add e3,R0
adc e4,R1
adc e5,c0 ; (addiere moeglichen Ueberlauf)
mul a2,b1 ; Term 3
add e2,R0
adc e3,R1
adc e4,c0
adc e5,c0
mul a1,b3 ; Term 4
add e3,R0
adc e4,R1
adc e5,c0
mul a1,b2 ; Term 5
add e2,R0
adc e3,R1
adc e4,c0
adc e5,c0
mul a1,b1 ; Term 6
add e1,R0
adc e2,R1
adc e3,c0
adc e4,c0
adc e5,c0
;
; fertig.
nop
; Ergebnis sollte sein hex 02540BE400

Die vollständige Abarbeitung braucht

● 10 Taktzyklen für das Laden der Konstanten,


● 6 Taktzyklen für das Löschen der Register, und
● 33 Taktzyklen für die Multiplikation.

Zum Seitenanfang

©2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechnen/hardmult.html1/20/2009 7:35:58 PM
AVR-Tutorial

Pfad: Home => AVR-Übersicht => Tutorium

Tutorial für das Erlernen der


Assemblersprache von
AVR-Einchip-Prozessoren AT90Sxxxx
von ATMEL anhand geeigneter
praktischer Beispiele.
Einfache
Einführungsbeispiele, Tutorial

(Die Links auf die *.asm-Dateien zum Herunterladen mit gedrückter Shift-Taste anklicken.)
HTML- ASM-
Erläuterung zum Inhalt
Format Format
Umgang mit dem Board kennenlernen, Ausgabe über den Port an die
Test1 Test1 angeschlossenen Leuchtdioden, Grundstruktur von Assembler, -direktiven und -
befehlen kennenlernen. Die Lampen blinken mit 800 Hz Takt.
Eingabe von einem Port lesen, das Aufrufen von Unterprogrammen, Stack-
(Stapel-Befehle), Binäre Rechen- Operationen (AND, OR, ROL, etc.), Bedingte
Test2 Test2 Verzweigungen (SBIx, BRxx). Das Drücken der Schalter 0 und 1 soll die
Lampen 0 und 1 anmachen, das Drücken eines der Schalter 2 bis 6 die anderen
Lampen. Das Drücken von Schalter 7 macht alle Lampen aus.
Timer im Polling modus ansteuern, MOV-Befehl. Ein Loop im Hauptprogramm
Test3 Test3 fragt den Hardware-Zähler ab, bis dieser Null erreicht, dann wird der
Softwarezähler um Eins erhöht und auf den LEDs ausgegeben.
Timer im Interrupt modus, Interrupts, Interrupt-Vektoren, BCD-Arithmetik.
Hauptprogramm-Loop fragt oberes Byte des Software-Zählers ab, bis dieser hex
3D erreicht hat. Dann den Timer, bis dieser 09 erreicht hat (eine Sekunde = dez
15625 = hex 3D09 Zählerimpulse). Die Zähler werden auf Null gesetzt und eine
Test4 Test4
Sekunde weitergezählt. Die Sekunden werden als gepackte BCD-Zahl behandelt
(eine Ziffer zu vier Bit, 1 Byte entspricht zwei Ziffern), Die Sekunden werden
bei Erreichen von 60 wieder auf Null gesetzt. Der Sekundenstand wird auf den
LEDs ausgegeben.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_tut.html1/20/2009 7:36:01 PM
AVR-Tutorium, Teil 1

Pfad: Home => AVR-Übersicht => Tutorium => Teil 1

; Test 1: Board kennenlernen, Ausgabe an die


Leuchtdioden.

; Was es hier zu lernen gibt:


; - Einen Ausgabe-Port ansteuern (Port B mit den LEDs)
; - Aus welchen Teilen ein Programm besteht.

; Von mir verwendete Konventionen:


; - Gross geschriebene Wörter kennzeichnen vordefinierte Befehlsworte
; oder mit dem Prozessortyp vordefinierte Ports.
; - Klein geschriebene Worte sind von mir definiert und willkürlich
; gewählt.

; Prozessor definieren
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Die Befehle NOLIST und LIST schalten das Auflisten der INCLUDE-Datei
; in der Datei TEST1.LST aus.

; Register definieren
;
; Dieses Register wird für die Zwischenspeicherung der Zahlen
; verwendet. Mit dem Befehl .DEF kriegt eins der 32 8-Bit-Register
; einen Namen (hier: mp), den man sich einfacher merken kann als
; R16. Ausserdem kann man einfacher Register verlegen, wenn man sie
; über einen Namen anspricht.

.DEF mp = R16

; Restart
;
; Bis jetzt war alles Vorgeplänkel. Hier beginnt nun das Programm.
; mit dem Reset- und Interrupt-Sprung-Teil. Dieser Teil
; produziert die ersten Programm-Bytes an der Adresse 0000 und
; folgende.
; Vorerst besteht dieser Teil nur aus einem Sprungbefehl in das
; Hauptprogramm. Dieser Befehl wird bei jedem Neustart des Pro-
; zessors ausgeführt. Ein Neustart wird bei Power-On, bei einem
; Hardware-Reset am Reset-Pin oder durch den Watchdog-Timer
; ausgelöst. Der Watchdog ist in diesem Programm nicht aktiv.
; In allen Fällen wird ein Sprung zum Programm mit dem Namen
; "main" ausgeführt.
; RJMP heisst "Relative Jump" oder relativer Sprung. Bei dem rela-
; tiven Sprung wird in dem Befehlswort eine relative Distanz mit
; angegeben, die der Assembler aus der Differenz zwischen der Adresse
; des Ziels (main) und der aktuellen Adresse ausrechnet. Die Sprung-
; Distanz darf 2 kB vorwärts oder rückwärts nicht überschreiten und
; es gibt Fehlermeldungen.

RJMP main

; Hier beginnt das Hauptprogramm mit dem Namen "main". Als erstes
; muss deshalb ein sogenanntes Label gesetzt werden. Ein Label ist
; ein frei definierter Name, gefolgt von einem Doppelpunkt. Zur
; besseren Übersicht beginnen alle Label in Spalte 1 einer Zeile,
; alle Programmbefehle jedoch mit einem oder mehr Leerzeichen oder TAB.
; Hinter dem Label kann schon ein Programmbefehl stehen, getrennt
; mittels Leerzeichen oder TAB. Habe ich aber hier nicht gemacht.

main:

; Als erstes muss der Port B, an den die LEDs angeschlossen sind, als
; Ausgang definiert werden. Dies macht man, indem man acht Einsen in
; das Datenrichtungs-Register des Ports B schreibt. Das Datenrichtungs-
; Register von Port B heisst DDRB (Data Direction Register B). Das er-
; fordert zwei Schritte: Erstens wird der Binärwert 1111.1111 in ein
; Register geschrieben:

LDI mp,0b11111111

; Der Befehl LDI (LoaD Immediate) lädt einen 8-Bit-Wert in das Register
; mp. Dieser Befehl ist nur für die Register R16 bis R31 zulässig, des-
; halb ist mp am Programmanfang als Register R16 definiert worden. Die
; Befehle mit zwei Parametern sind durchgängig so aufgebaut, dass der
; erste Parameter (Register mp) immer das Ziel angibt, in dem das Ergeb-
; nis gespeichert wird. Nach der Durchführung dieses Befehls enthält
; das Register 16 den Binärwert 11111111, hexadezimal FF oder dezimal
; 255.
; Die Schreibweise "0b..." kennzeichnet immer eine Binärzahl, mit "0x..."
; wird eine Hexadezimalzahl angegeben. Die führende Null lässt den
; Assembler eine gültige Zahl erwarten. Zahlen ohne diesen Vorsatz sind
; automatisch dezimal ( LDI mp,255 wäre gleichwertig).

; Dieser Wert muss jetzt in das Datenrichtungs-Register gegeben


; werden, damit der Port B in ganzer Breite zu Ausgängen wird. Eine 1
; im Datenrichtungsregister macht den zugehörigen Pin zum Ausgang, eine
; 0 zum Eingang.

OUT DDRB,mp

; Der Befehl OUT schreibt Registerinhalte (hier: mp oder R16) auf einen
; Port (hier DDRB). DDRB ist in der Datei "8515def.inc" definiert, die
; über den .DEVICE-Befehl oder wie hier über den .INCLUDE-Befehl in den
; Assembler-Text eingebunden ist. Dadurch muss man sich die Portnummer
; des Datenrichtungsregisters nicht merken.

; Dieser Programmteil gibt nun abwechselnd Nullen und Einsen auf die
; Portausgänge aus. Die LEDs leuchten in einem sehr schnellen Takt.
; Da dieser Programmteil unendlich lang wiederholt ist, kriegt er das
; Label loop, da nach dem Klappern der Bits wieder dorthin gesprungen
; werden muss.

loop:
LDI mp,0x00
OUT PORTB,mp

; LDI lädt erst mal acht Bits Nullen in das Universalregister mp.
; OUT gibt diese Nullen auf dem Port B aus. Diesmal kommen sie in das
; Datenausgaberegister von Port B (PORTB).
; Die Nullen lassen die LEDs leuchten, da sie über 1 k an die Versor-
; gungsspannung geführt sind (0=an, 1=aus).

LDI mp,0xFF
OUT PORTB,mp

; Anschliessend kommen acht Einsen in das Register und von da aus in


; den Datenausgabe-Port. Das macht die Lämpchen wieder aus.

RJMP loop

; Mit diesem relativen Sprung geht es wieder zurück an den Anfang der
; Schleife, und das Ganze dauert ewiglich.
; Bei 4 MHz Quarzfrequenz dauert jeder LDI- und OUT-Befehl in der Schleife
; 250 ns, der RJMP braucht zwei Takte und dauert 500 ns. Macht zusammen
; 1500 ns, die LEDs werden folglich mit 667 kHz angesteuert.

; Nach dem Assemblieren sollte das Programm acht Worte haben. In der
; Datei TEST1.LST kann man sich das Ergebnis der Assemblierung an-
; schauen.

; Dieses war der erste Streich ...

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/test1.html1/20/2009 7:36:02 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/test1.asm

; Test 1: Board kennenlernen, Ausgabe an die Leuchtdioden.


; Was es hier zu lernen gibt:
; - Einen Ausgabe-Port ansteuern (Port B mit den LEDs)
; - Aus welchen Teilen ein Programm besteht.
; Von mir verwendete Konventionen:
; - Gross geschriebene Wörter kennzeichnen vordefinierte Befehlsworte
; oder mit dem Prozessortyp vordefinierte Ports.
; - Klein geschriebene Worte sind von mir definiert und willkürlich
; gewählt.
; Prozessor definieren
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Die Befehle NOLIST und LIST schalten das Auflisten der INCLUDE-Datei
; in der Datei TEST1.LST aus.
; Register definieren
;
; Dieses Register wird für die Zwischenspeicherung der Zahlen
; verwendet. Mit dem Befehl .DEF kriegt eins der 32 8-Bit-Register
; einen Namen (hier: mp), den man sich einfacher merken kann als
; R16. Ausserdem kann man einfacher Register verlegen, wenn man sie
; über einen Namen anspricht.
.DEF mp = R16
; Restart
;
; Bis jetzt war alles Vorgeplänkel. Hier beginnt nun das Programm.
; mit dem Reset- und Interrupt-Sprung-Teil. Dieser Teil
; produziert die ersten Programm-Bytes an der Adresse 0000 und
; folgende.
; Vorerst besteht dieser Teil nur aus einem Sprungbefehl in das
; Hauptprogramm. Dieser Befehl wird bei jedem Neustart des Pro-
; zessors ausgeführt. Ein Neustart wird bei Power-On, bei einem
; Hardware-Reset am Reset-Pin oder durch den Watchdog-Timer
; ausgelöst. Der Watchdog ist in diesem Programm nicht aktiv.
; In allen Fällen wird ein Sprung zum Programm mit dem Namen
; "main" ausgeführt.
; RJMP heisst "Relative Jump" oder relativer Sprung. Bei dem rela-
; tiven Sprung wird in dem Befehlswort eine relative Distanz mit
; angegeben, die der Assembler aus der Differenz zwischen der Adresse
; des Ziels (main) und der aktuellen Adresse ausrechnet. Die Sprung-
; Distanz darf 2 kB vorwärts oder rückwärts nicht überschreiten und
; es gibt Fehlermeldungen.
rjmp main
; Hier beginnt das Hauptprogramm mit dem Namen "main". Als erstes
; muss deshalb ein sogenanntes Label gesetzt werden. Ein Label ist
; ein frei definierter Name, gefolgt von einem Doppelpunkt. Zur
; besseren Übersicht beginnen alle Label in Spalte 1 einer Zeile,
; alle Programmbefehle jedoch mit einem oder mehr Leerzeichen oder TAB.
; Hinter dem Label kann schon ein Programmbefehl stehen, getrennt
; mittels Leerzeichen oder TAB. Habe ich aber hier nicht gemacht.
main:
; Als erstes muss der Port B, an den die LEDs angeschlossen sind, als
; Ausgang definiert werden. Dies macht man, indem man acht Einsen in
; das Datenrichtungs-Register des Ports B schreibt. Das Datenrichtungs-
; Register von Port B heisst DDRB (Data Direction Register B). Das er-
; fordert zwei Schritte: Erstens wird der Binärwert 1111.1111 in ein
; Register geschrieben:
ldi mp,0b11111111
; Der Befehl LDI (LoaD Immediate) lädt einen 8-Bit-Wert in das Register
; mp. Dieser Befehl ist nur für die Register R16 bis R31 zulässig, des-
; halb ist mp am Programmanfang als Register R16 definiert worden. Die
; Befehle mit zwei Parametern sind durchgängig so aufgebaut, dass der
; erste Parameter (Register mp) immer das Ziel angibt, in dem das Ergeb-
; nis gespeichert wird. Nach der Durchführung dieses Befehls enthält
; das Register 16 den Binärwert 11111111, hexadezimal FF oder dezimal
; 255.
; Die Schreibweise "0b..." kennzeichnet immer eine Binärzahl, mit "0x..."
; wird eine Hexadezimalzahl angegeben. Die führende Null lässt den
; Assembler eine gültige Zahl erwarten. Zahlen ohne diesen Vorsatz sind
; automatisch dezimal ( LDI mp,255 wäre gleichwertig).
; Dieser Wert muss jetzt in das Datenrichtungs-Register gegeben
; werden, damit der Port B in ganzer Breite zu Ausgängen wird. Eine 1
; im Datenrichtungsregister macht den zugehörigen Pin zum Ausgang, eine
; 0 zum Eingang.
out DDRB,mp
; Der Befehl OUT schreibt Registerinhalte (hier: mp oder R16) auf einen
; Port (hier DDRB). DDRB ist in der Datei "8515def.inc" definiert, die
; über den .DEVICE-Befehl oder wie hier über den .INCLUDE-Befehl in den
; Assembler-Text eingebunden ist. Dadurch muss man sich die Portnummer
; des Datenrichtungsregisters nicht merken.
; Dieser Programmteil gibt nun abwechselnd Nullen und Einsen auf die
; Portausgänge aus. Die LEDs leuchten in einem sehr schnellen Takt.
; Da dieser Programmteil unendlich lang wiederholt ist, kriegt er das
; Label loop, da nach dem Klappern der Bits wieder dorthin gesprungen
; werden muss.
loop:
ldi mp,0x00
out PORTB,mp
; LDI lädt erst mal acht Bits Nullen in das Universalregister mp.
; OUT gibt diese Nullen auf dem Port B aus. Diesmal kommen sie in das
; Datenausgaberegister von Port B (PORTB).
; Die Nullen lassen die LEDs leuchten, da sie über 1 k an die Versor-
; gungsspannung geführt sind (0=an, 1=aus).
ldi mp,0xFF
out PORTB,mp
; Anschliessend kommen acht Einsen in das Register und von da aus in
; den Datenausgabe-Port. Das macht die Lämpchen wieder aus.
rjmp loop
; Mit diesem relativen Sprung geht es wieder zurück an den Anfang der
; Schleife, und das Ganze dauert ewiglich.
; Bei 4 MHz Quarzfrequenz dauert jeder LDI- und OUT-Befehl in der Schleife
; 250 ns, der RJMP braucht zwei Takte und dauert 500 ns. Macht zusammen
; 1500 ns, die LEDs werden folglich mit 667 kHz angesteuert.
;
; Nach dem Assemblieren sollte das Programm acht Worte haben. In der
; Datei TEST1.LST kann man sich das Ergebnis der Assemblierung an-
; schauen.
; Dieses war der erste Streich ...

http://www.avr-asm-tutorial.net/avr_de/quellen/test1.asm1/20/2009 7:36:04 PM
AVR-Tutorium, Teil 2

Pfad: Home => AVR-Übersicht => Tutorium => Teil 2

; Test 2: Board kennenlernen: Eingabe von


einem Port

; Was man hier dazu lernen kann:


; - Eingabe von einem Port lesen
; - Das Aufrufen von Unterprogrammen, Stack- (Stapel-Befehle)
; - Binäre Rechen Operationen (AND, OR, ROL, etc.)
; - Bedingte Verzweigungen (SBIx, BRxx)

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Ein Universalregister definieren:

.DEF mp = R16

; Der Reset-Sprungbefehl an Adresse 0:

RJMP main

; Hier beginnt das Hauptprogramm

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer


OUT SPL,mp
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Diese Befehle richten einen Stack im SRAM ein. Ein Stack wird immer
; dann gebraucht, wenn Unterprogramme oder Interrupts aufgerufen werden.
; Beim Aufruf muss der aktuelle Zählerstand der Bearbeitung in einem
; Speicher abgelegt werden, damit nach Beendigung wieder an die auf-
; rufende Stelle zurückgekehrt werden kann. Der Stack wird immer am
; oberen Speicherende des SRAM angelegt. Das Speicherende des jeweili-
; gen Chips ist in der Datei "xxxxdef.inc" mit dem Namen RAMEND defi-
; niert.
; Wird ein Byte auf dem Stapel oder Stack abgelegt, dann wird ein
; Byte in das SRAM geschrieben (an die Adresse SPH:SPL), dann wird der
; Stapelzähler SPH:SPL um Eins verringert. Weiteres Ablegen bringt den
; Zeiger näher an den Anfang des SRAMs. Wird ein Wert aus dem Stapel
; entnommen, dann wird der Zeiger um eins erhöht und der Wert ausgelesen.
; Der jeweils zuletzt im SRAM abgelegte Wert kommt bei der Entnahme
; wieder als erster heraus (Last-in-First-Out-Struktur).
; Da der Programmzähler und die weitere Adressverwaltung 16 Bits
; Breite hat, alle Register und das SRAM aber 8 Bits, muss man jeweils
; mit 2 Bytes zu 8 Bits oder einem Wort zu 16 Bits arbeiten. Der
; SRAM-Speicher hat 16 Bit Adresse, also gibt es den Port SPL für die
; unteren 8 Bits, den Port SPH für die oberen 8 Bits der Adresse. Zusam-
; men ist SPH:SPL ein 16-Bit-Zeiger in das SRAM.
; Die Rechenoperationen LOW und HIGH veranlassen den Assembler, das
; 16-Bit-Wort RAMEND jeweils zu je 8-Bits aufzuteilen, damit es in die
; Ports SPL und SPH übertragen werden kann.

; An Port D sind die Schalter angeschlossen. Der Port D wird gelesen.


; Sein Datenrichtungsregister muss also acht Nullen kriegen:

LDI mp,0x00 ; 8 Nullen in Universalregister


OUT DDRD,mp ; an Datenrichtungsregister

; Die Schalter verbinden die Eingänge des Ports D mit GND. Damit bei
; offenem Schalter ein definierter Pegel herrscht, können die Pull-Up-
; Widerstände eingeschaltet werden. Das ist an sich auf dem STK200 nicht
; erforderlich, da diese extern vorhanden sind. Aus pädagischen Gründen
; schalten wir sie trotzdem ein. Das erreicht man durch das Schreiben
; von Einsen in das Datenausgangsregister:

LDI mp,0xFF ; 8 Einsen in Universalregister


OUT PORTD,mp ; und an Port D (das sind jetzt die Pull-Ups!)

; Port B mit den LEDs soll wieder als Ausgang dienen (siehe TEST1), die
; Lampen sollen zu Beginn alle aus sein.

LDI mp,0xFF ; 8 Einsen in Universalregister


OUT DDRB,mp ; und in Datenrichtungsregister
OUT PORTB,mp ; und an alle Ausgänge

; Das Drücken der Schalter 0 und 1 soll die Lampen 0 und 1 anmachen,
; das Drücken eines der Schalter 2 bis 6 die anderen Lampen. Das
; Drücken von Schalter 7 macht alle Lampen aus.
; Im Hauptloop erfolgt die Abfrage der Schalter, wenn die Bedingungen
; erfüllt sind, wird zu den jeweiligen Unterprogrammen verzeigt.

loop:

; Abfrage von Schalter 0 (einfachst)


; Überspringe den nächsten Befehl (Aufruf des Unterprogrammes zum
; Anmachen der Lampe 0), wenn das 0-te Bit im Port D eine Eins ist
; (Schalter aus, Pull-Up erzeugt eine Eins). Das Unterprogramm
; Lampe 0 steht weiter hinten. Beim RCALL wird die aktuelle Adresse
; auf den Stapel abgelegt, beim Rücksprung wird diese wieder vom Stapel
; genommen und das Programm mit dem Befehl nach RCALL fortgesetzt. Weil
; mit dem SBIS-Befehl immer nur ein Befehl übersprungen wird, muss es
; sich um einen Ein-Byte-Befehl handeln. RCALL ist ein solcher, der
; absolute CALL-Befehl wäre ein 2-Byte-Befehl und ginge nicht!

SBIS PIND,0 ; Springe, wenn Bit 0 im Port D Eins ist


RCALL Lampe0 ; Führe ein relativ angegebenes Unterprogramm aus

; Nach Abarbeiten des Unterprogrammes und beim Überspringen des Unter-


; programmes wird nun nächste Befehl durchgeführt.

; Abfrage von Schalter 1 (exotisch)


; Die Ports sind in den Adressraum des SRAMs gespiegelt, die Adresse
; ergibt sich durch Addition von 20 hex. Anstelle der IN/OUT-Befehle
; können auch die Lade-/Speicher-Befehle mit Zeigern verwendet werden.

.EQU d_in_spiegel=PIND + $20

; Mit dem Registerpaar R27:R26 kann ein Zeiger X in das SRAM konstruiert
; werden, mit dem LD-Befehl kann der Inhalt des Ports gelesen werden, als
; wenn es ein SRAM-Byte wäre.

LDI R26,LOW(d_in_spiegel) ; unteres Byte Zeiger


LDI R27,HIGH(d_in_spiegel) ; oberes Byte Zeiger
LD mp,X ; Lade Register aus Zeiger auf PIND

; Isoliere Pin1 mit AND-Befehl und teste auf Null

ANDI mp,0b00000010 ; AND Bit 1

; Überspringe die folgenden Befehle, wenn nicht Null bei AND herauskam
; (= Bit 1 war Eins, Schalter 1 ist aus). Der Sprungbefehl ist für eine
; größere Anzahl Befehle geeignet, da zu einem Label verzweigt wird.

BRNE weiter ; Verzweige nach weiter, falls nicht Null


RCALL Lampe1 ; Führe Unterprogramm Lampe1 aus

; Schalter 2 bis 6
; Einlesen des Ports D in ein Register, Maskieren der anderen Schalter,
; Vergleich mit Schalter 2 bis 6,
; Vergleich mit LEDs 2 bis 7 anmachen

weiter: IN mp,PIND ; Lese Port D


ORI mp,0b10000011 ; Maskiere Schalter 0, 1 und 7
CPI mp,0b11111111 ; Irgendein Schalter gedrückt?
BREQ sw7 ; Verzweige nach sw7, falls = $FF
IN mp,PINB ; Lese LED-Port
ANDI mp,0b00000011 ; Lampen 2 bis 7 anmachen
OUT PORTB,mp ; an LED-Port

sw7: IN mp,PIND ; Lese Schalter-Port


ROL mp ; Schiebe siebtes Bit in das Carry-Flag
BRCS endloop ; Siebtes Bit ist 1 (BRanch if Carry is Set)
LDI mp,0xFF ; Alle Lampen aus
OUT PORTB,mp

endloop:
RJMP loop

; Unterprogramm Lampe 0

; schaltet Lampe 0 ein.

Lampe0: IN mp,PINB ; Lese aktuellen Zustand von Port B


ANDI mp,0b11111110 ; Lösche Bit 0 mit UND-Befehl
OUT PORTB,mp ; Schreibe Ergebnis zurück
RET ; Hole Rücksprungadresse vom Stapel und kehre zurück

; Unterprogramm Lampe 1

; schaltet Lampe 1 ein

Lampe1: IN mp,PINB ; Lese Zustand von Port B


CBR mp,0b00000010 ; Lösche Bit 1 mit CBR-Befehl
OUT PORTB,mp ; Schreibe Ergebnis zurück
RET ; Adresse vom Stapel und zurück

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/test2.html1/20/2009 7:36:08 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/test2.asm

; Test 2: Board kennenlernen: Eingabe von einem Port


; Was man hier dazu lernen kann:
; - Eingabe von einem Port lesen
; - Das Aufrufen von Unterprogrammen, Stack- (Stapel-Befehle)
; - Binäre Rechen Operationen (AND, OR, ROL, etc.)
; - Bedingte Verzweigungen (SBIx, BRxx)
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Ein Universalregister definieren:
.DEF mp = R16
; Der Rest-Sprungbefehl an Adresse 0:
rjmp main
; Hier beginnt das Hauptprogramm
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp
ldi mp,HIGH(RAMEND)
out SPH,mp
; Diese Befehle richten einen Stack im SRAM ein. Ein Stack wird immer
; dann gebraucht, wenn Unterprogramme oder Interrupts aufgerufen werden.
; Beim Aufruf muss der aktuelle Zählerstand der Bearbeitung in einem
; Speicher abgelegt werden, damit nach Beendigung wieder an die auf-
; rufende Stelle zurückgekehrt werden kann. Der Stack wird immer am
; oberen Speicherende des SRAM angelegt. Das Speicherende des jeweili-
; gen Chips ist in der Datei "xxxxdef.inc" mit dem Namen RAMEND defi-
; niert.
; Wird ein Byte auf dem Stapel oder Stack abgelegt, dann wird ein
; Byte in das SRAM geschrieben (an die Adresse SPH:SPL), dann wird der
; Stapelzähler SPH:SPL um Eins verringert. Weiteres Ablegen bringt den
; Zeiger näher an den Anfang des SRAMs. Wird ein Wert aus dem Stapel
; entnommen, dann wird der Zeiger um eins erhöht und der Wert ausgelesen.
; Der jeweils zuletzt im SRAM abgelegte Wert kommt bei der Entnahme
; wieder als erster heraus (Last-in-First-Out-Struktur).
; Da der Programmzähler und die weitere Adressverwaltung 16 Bits
; Breite hat, alle Register und das SRAM aber 8 Bits, muss man jeweils
; mit 2 Bytes zu 8 Bits oder einem Wort zu 16 Bits arbeiten. Der
; SRAM-Speicher hat 16 Bit Adresse, also gibt es den Port SPL für die
; unteren 8 Bits, den Port SPH für die oberen 8 Bits der Adresse. Zusam-
; men ist SPH:SPL ein 16-Bit-Zeiger in das SRAM.
; Die Rechenoperationen LOW und HIGH veranlassen den Assembler, das
; 16-Bit-Wort RAMEND jeweils zu je 8-Bits aufzuteilen, damit es in die
; Ports SPL und SPH übertragen werden kann.
; An Port D sind die Schalter angeschlossen. Der Port D wird gelesen.
; Sein Datenrichtungsregister muss also acht Nullen kriegen:
ldi mp,0x00 ; 8 Nullen in Universalregister
out DDRD,mp ; an Datenrichtungsregister
; Die Schalter verbinden die Eingänge des Ports D mit GND. Damit bei
; offenem Schalter ein definierter Pegel herrscht, können die Pull-Up-
; Widerstände eingeschaltet werden. Das ist beim STK200 nicht nötig,
; weil diese extern schon auf dem Board vorhanden sind. Aus pädagischen
; Gründen schalten wir sie trotzdem ein. Das erreicht man durch das
; Schreiben von Einsen in das Datenausgangsregister:
ldi mp,0xFF ; 8 Einsen in Universalregister
out PORTD,mp ; und an Port D (das sind jetzt die Pull-Ups!)
; Port B mit den LEDs soll wieder als Ausgang dienen (siehe TEST1), die
; Lampen sollen zu Beginn alle aus sein.
ldi mp,0xFF ; 8 Einsen in Universalregister
out DDRB,mp ; und in Datenrichtungsregister
out PORTB,mp ; und an alle Ausgänge
; Das Drücken der Schalter 0 und 1 soll die Lampen 0 und 1 anmachen,
; das Drücken eines der Schalter 2 bis 6 die anderen Lampen. Das
; Drücken von Schalter 7 macht alle Lampen aus.
; Im Hauptloop erfolgt die Abfrage der Schalter, wenn die Bedingungen
; erfüllt sind, wird zu den jeweiligen Unterprogrammen verzeigt.
loop:
; Abfrage von Schalter 0 (einfachst)
; Überspringe den nächsten Befehl (Aufruf des Unterprogrammes zum
; Anmachen der Lampe 0), wenn das 0-te Bit im Port D eine Eins ist
; (Schalter aus, Pull-Up erzeugt eine Eins). Das Unterprogramm
; Lampe 0 steht weiter hinten. Beim RCALL wird die aktuelle Adresse
; auf den Stapel abgelegt, beim Rücksprung wird diese wieder vom Stapel
; genommen und das Programm mit dem Befehl nach RCALL fortgesetzt. Weil
; mit dem SBIS-Befehl immer nur ein Befehl übersprungen wird, muss es
; sich um einen Ein-Byte-Befehl handeln. RCALL ist ein solcher, der
; absolute CALL-Befehl wäre ein 2-Byte-Befehl und ginge nicht!

sbis PIND,0 ; Springe, wenn Bit 0 im Port D Eins ist


rcall Lampe0 ; Führe ein relativ angegebenes Unterprogramm aus
; Nach Abarbeiten des Unterprogrammes und beim Überspringen des Unter-
; programmes wird nun nächste Befehl durchgeführt.
; Abfrage von Schalter 1 (exotisch)
; Die Ports sind in den Adressraum des SRAMs gespiegelt, die Adresse
; ergibt sich durch Addition von 20 hex. Anstelle der IN/OUT-Befehle
; können auch die Lade-/Speicher-Befehle mit Zeigern verwendet werden.
.EQU d_in_spiegel=PIND + $20
; Mit dem Registerpaar R27:R26 kann ein Zeiger X in das SRAM konstruiert
; werden, mit dem LD-Befehl kann der Inhalt des Ports gelesen werden, als
; wenn es ein SRAM-Byte wäre.
ldi R26,LOW(d_in_spiegel) ; unteres Byte Zeiger
ldi R27,HIGH(d_in_spiegel) ; oberes Byte Zeiger
ld mp,X ; Lade Register aus Zeiger auf PIND
; Isoliere Pin1 mit AND-Befehl und teste auf Null
andi mp,0b00000010 ; AND Bit 1
; Überspringe die folgenden Befehle, wenn nicht Null bei AND herauskam
; (= Bit 1 war Eins, Schalter 1 ist aus). Der Sprungbefehl ist für eine
; größere Anzahl Befehle geeignet, da zu einem Label verzweigt wird.
brne weiter ; Verzweige nach weiter, falls nicht Null
rcall Lampe1 ; Führe Unterprogramm Lampe1 aus
; Schalter 2 bis 6
; Einlesen des Ports D in ein Register, Maskieren der anderen Schalter,
; Vergleich mit Schalter 2 bis 6,
; Vergleich mit LEDs 2 bis 7 anmachen
weiter:
in mp,PIND ; Lese Port D
ori mp,0b10000011 ; Maskiere Schalter 0, 1 und 7
cpi mp,0b11111111 ; Irgendein Schalter gedrückt?
breq sw7 ; Verzweige nach sw7, falls = $FF
in mp,PINB ; Lese LED-Port
andi mp,0b00000011 ; Lampen 2 bis 7 anmachen
out PORTB,mp ; an LED-Port
sw7:
in mp,PIND ; Lese Schalter-Port
rol mp ; Schiebe siebtes Bit in das Carry-Flag
brcs endloop ; Siebtes Bit ist 1 (BRanch if Carry is Set)
ldi mp,0xFF ; Alle Lampen aus
out PORTB,mp
endloop:
rjmp loop
;
; Unterprogramm Lampe 0
; schaltet Lampe 0 ein.
Lampe0:
in mp,PINB ; Lese aktuellen Zustand von Port B
andi mp,0b11111110 ; Lösche Bit 0 mit UND-Befehl
out PORTB,mp ; Schreibe Ergebnis zurück
ret ; Hole Rücksprungadresse vom Stapel und kehre zurück
; Unterprogramm Lampe 1
; schaltet Lampe 1 ein
Lampe1:
in mp,PINB ; Lese Zustand von Port B
cbr mp,0b00000010 ; Lösche Bit 2 mit CBR-Befehl
out PORTB,mp ; Schreibe Ergebnis zurück
ret ; Adresse vom Stapel und zurück

http://www.avr-asm-tutorial.net/avr_de/quellen/test2.asm1/20/2009 7:36:12 PM
AVR-Tutorium, Teil 3

Pfad: Home => AVR-Übersicht => Tutorium => Teil 3

; Test 3: Board kennenlernen, Timer im Polling


mode

; Was hier Neues zu lernen ist:


; - Timer im Polling modus
; - MOV-Befehl

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Universalregister definieren

.DEF mp = R16

; Zähler für Anzahl Nulldurchgänge

.DEF z1 = R0

; Reset-Vektor auf Adresse 0000

RJMP main

; Hauptprogramm beginnt hier

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer (Unterprogramme!)


OUT SPL,mp
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Software-Zähler-Register auf Null setzen


LDI mp,0 ; z1 kann nicht direkt gesetzt werden, da R0
MOV z1,mp ; Kopieren von mp in das Register z1

; Vorteiler des Zählers = 1024, 4 MHz/1024 = 3906,25 Hz


; entspricht einem Zählimpuls alle 256 µs.
LDI mp,0x05 ;Initiate Timer/Counter 0 Vorteiler
OUT TCCR0,mp ; an Timer 0 Control Register

; Port B ist LED-Port

LDI mp,0xFF ; alle Bits als Ausgang


OUT DDRB,mp ; in Datenrichtungsregister

; Hauptprogramm-Loop fragt Zähler ab, bis dieser Null erreicht,


; dann wird der Softwarezähler um Eins erhöht und auf den LEDs
; ausgegeben. Das mit einer Frequenz von 15,25878906 Hz der Fall, entsprechend
; alle 65,536 ms.
loop:
IN mp,TCNT0 ; Inhalt des 8-Bit-Zählers lesen
CPI mp,0 ; auf Null testen
BRNE loop ; Wenn nicht null, dann wieder loop
RCALL IncZ1 ; Unterprogramm Software-Zähler erhöhen
RCALL Display ; Unterprogramm Zählerstand ausgeben
warte: IN mp,TCNT0 ; Inhalt Zähler 0 lesen
CPI mp,0 ; auf Null testen
BREQ warte ; Warte bis nicht mehr Null
RJMP loop ; Nächste Runde

IncZ1: INC z1 ; Erhöhe Software-Zähler


RET ; Kehre zurück ins Hauptprogramm

Display:
MOV mp,z1 ; Zählerstand nach mp kopieren
COM mp ; Einer-Komplement XOR(FF) wg. Lampen
OUT PORTB,mp ; Software-Zählerstand an LEDs
RET ; Zurück zum Hauptprogramm

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/test3.html1/20/2009 7:36:14 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/test3.asm

; Test 3: Board kennenlernen, Timer im Polling mode


; Was hier Neues zu lernen ist:
; - Timer im Polling modus
; - MOV-Befehl
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Universalregister definieren
.DEF mp = R16
; Zähler für Anzahl Nulldurchgänge
.DEF z1 = R0
; Reset-Vektor auf Adresse 0000
rjmp main
; Hauptprogramm beginnt hier
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer (Unterprogramme!)
out SPL,mp
ldi mp,HIGH(RAMEND)
out SPH,mp
; Software-Zähler-Register auf Null setzen
ldi mp,0 ; z1 kann nicht direkt gesetzt werden, da R0
mov z1,mp ; Kopieren von mp in das Register z1
; Vorteiler des Zählers = 1024, 4 MHz/1024 = 3906,25 Hz,
; ergibt alle 256 µs einen Zählimpuls.
;
ldi mp,0x05 ;Initiate Timer/Counter 0 Vorteiler
out TCCR0,mp ; an Timer 0 Control Register
; Port B ist LED-Port
ldi mp,0xFF ; alle Bits als Ausgang
out DDRB,mp ; in Datenrichtungsregister
; Hauptprogramm-Loop fragt Zähler ab, bis dieser Null erreicht,
; dann wird der Softwarezähler um Eins erhöht und auf den LEDs
; ausgegeben.
; Dadurch werden die 3906,25 noch einmal durch 256 geteilt, ergibt
; 15,25878906 Hz. Wer es lieber in Zeiten mag: 65,536 ms.
;
loop:
in mp,TCNT0 ; Inhalt des 8-Bit-Zählers lesen
cpi mp,0 ; auf Null testen
brne loop ; Wenn nicht null, dann wieder loop
rcall IncZ1 ; Unterprogramm Software-Zähler erhöhen
rcall Display ; Unterprogramm Zählerstand ausgeben
warte:
in mp,TCNT0 ; Inhalt Zähler 0 lesen
cpi mp,0 ; auf Null testen
breq warte ; Warte bis nicht mehr Null
rjmp loop ; Nächste Runde
IncZ1:
inc z1 ; Erhöhe Software-Zähler
ret ; Kehre zurück ins Hauptprogramm
Display:
mov mp,z1 ; Zählerstand nach mp kopieren
com mp ; Einer-Komplement XOR(FF) wg. Lampen
out PORTB,mp ; Software-Zählerstand an LEDs
ret ; Zurück zum Hauptprogramm

http://www.avr-asm-tutorial.net/avr_de/quellen/test3.asm1/20/2009 7:36:15 PM
AVR-Tutorium, Teil 4

Pfad: Home => AVR-Übersicht => Tutorium => Teil 4

; Test 4: Board kennenlernen, Timer im Interupt


mode

; Was hier Neues zu lernen ist:


; - Timer im Interrupt modus
; - Interrupts, Interrupt-Vektoren
; - BCD-Arithmetik

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Universalregister definieren

.DEF mp = R16

; Zähler Anzahl Nulldurchgänge, MSB Zähler, Software-Zähler

.DEF z1 = R0

; Arbeitsregister für die Interrupt-Service-Routine

.DEF ri = R1

; Register zum Zählen der Sekunden, gepackte BCD-Ziffern

.DEF sec = R2

; Reset-Vektor auf Adresse 0000

RJMP main

; Interrupt-Vektoren, fast alle blindgesetzt ausser dem Timer-Overflow


; RETI ist Rückkehr vom Interrupt mit Wiederherstellung des Interrupt-
; Flags im Status-Register. Wichtig: Sprung zur Interrupt-Service-
; Routine tc0i muss an der Adresse 0007 stehen.
; Mechanismus des Interrupts: Ist der Timer von 255 auf Null überge-
; laufen, dann wird das Programm unterbrochen, der Programmzähler auf
; dem Stapel abgelegt, der Befehl an der Adresse 0007 ausgeführt. Nach
; Beendigung des Interrupts wird der Programmzähler wieder hergestellt
; und mit dem unterbrochenen Programm fortgefahren.

; Die Interrupt-Vektoren zu je 1 Byte:

RETI ; Int0-Interrupt
RETI ; Int1-Interrupt
RETI ; TC1-Capture
RETI ; TC1-Compare A
RETI ; TC1-Compare B
RETI ; TC1-Overflow
RJMP tc0i ; Timer/Counter 0 Overflow, mein Sprung-Vektor
RETI ; Serial Transfer complete
RETI ; UART Rx complete
RETI ; UART Data register empty
RETI ; UART Tx complete
RETI ; Analog Comparator

; Interrupt-Service-Routine für den Zähler

tc0i: IN ri,SREG ; Rette den Inhalt des Flag-Registers


INC z1 ; Erhöhe Software-Zähler mit Bit 8-15
OUT SREG,ri ; Stelle Flag-Register wieder her
RETI ; Kehre vom Interrupt zurück

; Hauptprogramm beginnt hier

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer


OUT SPL,mp ; wegen Interrupts und Unterprogr.
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Software-Zähler-Register auf Null setzen


LDI mp,0 ; z1 kann nicht direkt gesetzt werden, da R0
MOV z1,mp ; Kopieren von 0 in den Software-Zähler
MOV sec,mp ; und Sekundenzähler auf Null

; Vorteiler des Zählers = 256, 4 MHz/256 = 15625 Hz = $3D09


LDI mp,0x04 ;Initiate Timer/Counter 0 Vorteiler
OUT TCCR0,mp ; an Timer 0 Control Register

; Port B ist LED-Port

LDI mp,0xFF ; alle Bits als Ausgang


OUT DDRB,mp ; in Datenrichtungsregister

; Interrupts bei Timer 0 einschalten


LDI mp,$02 ; Bit 1 setzen
OUT TIMSK,mp ; in Timer Interupt Mask Register
; Einfacher wäre dieser Befehl einfacher:
; SBI TIMSK,TOIE0 ; Timer Interrupt Mask Flag setzen
; Dieser Befehl geht aber nicht, weil mit SBI nur Ports bis 0x1F angesprochen werden
; können, und TIMSK liegt darüber.

; Alle Interrupts allgemein freigeben


SEI ; Gib Interrupts im Status-Register frei

; Hauptprogramm-Loop fragt oberes Byte des Zählers ab, bis dieser


; hex 3D erreicht hat. Dann den Timer, bis dieser 09 erreicht hat
; (eine Sekunde = dez 15625 = hex 3D09 Zählerimpulse). Die Zähler
; werden auf Null gesetzt und eine Sekunde weitergezählt. Die Se-
; kunden werden als gepackte BCD-Zahl behandelt (eine Ziffer zu
; vier Bit, 1 Byte entspricht zwei Ziffern), Die Sekunden werden
; bei Erreichen von 60 wieder auf Null gesetzt. Der Sekundenstand
; wird auf den LEDs ausgegeben.

loop: LDI mp,$3D ; Vergleichswert MSB


loop1: CP z1,mp ; Vergleiche mit MSB Zählerstand
BRLT loop1 ; z1 < mp, weiter warten
loop2: IN mp,TCNT0 ; Zähler LSB lesen
CPI mp,$09 ; mit LSB vergleichen
BRLT loop2 ; TCNT0 < 09, weiter warten
LDI mp,0 ; Null
OUT TCNT0,mp ; in Hardware-Zähler LSB
MOV z1,mp ; und in Software-Zähler MSB
RCALL IncSec ; Unterprogramm Sekunden-Zähler erhöhen
RCALL Display ; Unterprogramm Sekunden an LED ausgeben
RJMP loop ; Das Ganze von Vorne

; Unterprogramm eine Sekunde zum Sekundenzähler

; in BCD-Arithmetik! Unteres Nibble = Bit 0..3, Oberes N. = 4..7

IncSec: SEC ; Setze Carry-Flag für Addition


LDI mp,6 ; Provoziere Überlauf unteres Nibble
ADC sec,mp ; beim Addieren von 6 + 1 (Carry)
BRHS Chk60 ; Springe zum 60-Check, wenn Überlauf
SUB sec,mp ; Ziehe die 6 wieder ab
Chk60: LDI mp,$60 ; Vergleiche mit 60
CP sec,mp
BRLT SecRet ; Springe, wenn kleiner
LDI mp,256-$60 ; Lade Rest auf Null
ADD sec,mp ; Addiere auf Null
SecRet: RET ; Kehre zum Hauptprogramm zurück

; Unterprogramm zur Ausgabe des Sekundenzählers an die


LEDs
Display:
MOV mp,sec ; Zählerstand nach mp kopieren
COM mp ; Einer-Komplement = XOR(FF) wg. Lampen
OUT PORTB,mp ; Software-Zählerstand an LEDs
RET ; Zurück zum Hauptprogramm

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/test4.html1/20/2009 7:36:18 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/test4.asm

; Test 4: Board kennenlernen, Timer im Interupt mode


; Was hier Neues zu lernen ist:
; - Timer im Interrupt modus
; - Interrupts, Interrupt-Vektoren
; - BCD-Arithmetik
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Universalregister definieren
.DEF mp = R16
; Zähler Anzahl Nulldurchgänge, MSB Zähler, Software-Zähler
.DEF z1 = R0
; Arbeitsregister für die Interrupt-Service-Routine
.DEF ri = R1
; Register zum Zählen der Sekunden, gepackte BCD-Ziffern
.DEF sec = R2
; Reset-Vektor auf Adresse 0000
rjmp main
; Interrupt-Vektoren, fast alle blindgesetzt ausser dem Timer-Overflow
; RETI ist Rückkehr vom Interrupt mit Wiederherstellung des Interrupt-
; Flags im Status-Register. Wichtig: Sprung zur Interrupt-Service-
; Routine tc0i muss an der Adresse 0007 stehen.
; Mechanismus des Interrupts: Ist der Timer von 255 auf Null überge-
; laufen, dann wird das Programm unterbrochen, der Programmzähler auf
; dem Stapel abgelegt, der Befehl an der Adresse 0007 ausgeführt. Nach
; Beendigung des Interrupts wird der Programmzähler wieder hergestellt
; und mit dem unterbrochenen Programm fortgefahren.
; Die Interrupt-Vektoren zu je 1 Byte:
reti ; Int0-Interrupt
reti ; Int1-Interrupt
reti ; TC1-Capture
reti ; TC1-Compare A
reti ; TC1-Compare B
reti ; TC1-Overflow
rjmp tc0i ; Timer/Counter 0 Overflow, mein Sprung-Vektor
reti ; Serial Transfer complete
reti ; UART Rx complete
reti ; UART Data register empty
reti ; UART Tx complete
reti ; Analog Comparator
; Interrupt-Service-Routine für den Zähler
tc0i:
in ri,SREG ; Rette den Inhalt des Flag-Registers
inc z1 ; Erhöhe Software-Zähler mit Bit 8-15
out SREG,ri ; Stelle Flag-Register wieder her
reti ; Kehre vom Interrupt zurück
; Hauptprogramm beginnt hier
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; wegen Interrupts und Unterprogr.
ldi mp,HIGH(RAMEND)
out SPH,mp
; Software-Zähler-Register auf Null setzen
ldi mp,0 ; z1 kann nicht direkt gesetzt werden, da R0
mov z1,mp ; Kopieren von 0 in den Software-Zähler
mov sec,mp ; und Sekundenzähler auf Null
; Vorteiler des Zählers = 256, 4 MHz/256 = 15625 Hz = $3D09
ldi mp,0x04 ;Initiate Timer/Counter 0 Vorteiler
out TCCR0,mp ; an Timer 0 Control Register
; Port B ist LED-Port
ldi mp,0xFF ; alle Bits als Ausgang
out DDRB,mp ; in Datenrichtungsregister
; Interrupts bei Timer 0 einschalten
ldi mp,$02 ; Bit 1 setzen
out TIMSK,mp ; in Timer Interupt Mask Register
; Eigentlich könnte dieser Befehl folgendermassen aussehen:
; SBI TIMSK,TOIE0 ; Timer Interrupt Mask Flag setzen
; Das geht aber nicht, weil SBI nur bei Portnummern bis 0x1F
; geht, TIMSK liegt aber darüber. Deshalb der Umweg.
; Alle Interrupts allgemein freigeben
sei ; Gib Interrupts im Status-Register frei
; Hauptprogramm-Loop fragt oberes Byte des Zählers ab, bis dieser
; hex 3D erreicht hat. Dann den Timer, bis dieser 09 erreicht hat
; (eine Sekunde = dez 15625 = hex 3D09 Zählerimpulse). Die Zähler
; werden auf Null gesetzt und eine Sekunde weitergezählt. Die Se-
; kunden werden als gepackte BCD-Zahl behandelt (eine Ziffer zu
; vier Bit, 1 Byte entspricht zwei Ziffern), Die Sekunden werden
; bei Erreichen von 60 wieder auf Null gesetzt. Der Sekundenstand
; wird auf den LEDs ausgegeben.
loop:
ldi mp,$3D ; Vergleichswert MSB
loop1:
cp z1,mp ; Vergleiche mit MSB Zählerstand
brlt loop1 ; z1 < mp, weiter warten
loop2:
in mp,TCNT0 ; Zähler LSB lesen
cpi mp,$09 ; mit LSB vergleichen
brlt loop2 ; TCNT0 < 09, weiter warten
ldi mp,0 ; Null
out TCNT0,mp ; in Hardware-Zähler LSB
mov z1,mp ; und in Software-Zähler MSB
rcall IncSec ; Unterprogramm Sekunden-Zähler erhöhen
rcall Display ; Unterprogramm Sekunden an LED ausgeben
rjmp loop ; Das Ganze von Vorne
; Unterprogramm eine Sekunde zum Sekundenzähler
; in BCD-Arithmetik! Unteres Nibble = Bit 0..3, Oberes N. = 4..7
IncSec:
sec ; Setze Carry-Flag für Addition
ldi mp,6 ; Provoziere Überlauf unteres Nibble
adc sec,mp ; beim Addieren von 6 + 1 (Carry)
brhs Chk60 ; Springe zum 60-Check, wenn Überlauf
sub sec,mp ; Ziehe die 6 wieder ab
Chk60:
ldi mp,$60 ; Vergleiche mit 60
cp sec,mp
brlt SecRet ; Springe, wenn kleiner
ldi mp,256-$60 ; Lade Rest auf Null
add sec,mp ; Addiere auf Null
SecRet:
ret ; Kehre zum Hauptprogramm zurück
; Unterprogramm zur Ausgabe des Sekundenzählers an die LEDs
Display:
mov mp,sec ; Zählerstand nach mp kopieren
com mp ; Einer-Komplement = XOR(FF) wg. Lampen
out PORTB,mp ; Software-Zählerstand an LEDs
ret ; Zurück zum Hauptprogramm

http://www.avr-asm-tutorial.net/avr_de/quellen/test4.asm1/20/2009 7:36:19 PM
Zeitschleifen in AVR Assembler

Path: Home => AVR-Überblick => Zeitschleifen

Zeitschleifenprogrammierung in AVR
Assembler
Anfänger verzweifeln oft schon bei der Aufgabe, eine an einem Ausgangsport
angeschlossene LED zum Blinken zu bewegen. Das "Hello-World"-Programm der
AVR-Welt ist schon einigermaßen schwierig. Deshalb hier alles über Zeitschleifen,
wie man sie entwirft, einsetzt und näherungsweise und korrekt berechnet.

Überblick
1. 8-Bit-Register-Zeitschleife
2. 16-Bit-Doppelregister-Zeitschleife

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/index.html1/20/2009 7:36:21 PM
Zeitschleifen in AVR Assembler

Path: Home => AVR-Überblick => Zeitschleifen => 8-Bit-Register

Zeitschleife mit 8-Bit-Register in AVR


Assembler
Hier wird eine 8-Bit-Zeitschleife erklärt. Wenn Sie das alles schon wissen, blättern
Sie es trotzdem kurz durch. Die Zeitberechnungen und die Taktfrequenzen könnten
einiges Neues bringen, das bei den etwas komplizierteren Zeitschleifen behilflich sein
könnte.

Code einer 8-Bit-Schleife


Eine Zeitschleife mit einem 8-Bit-Register sieht in Assembler folgendermaßen aus:

.equ c1 = 200 ; Anzahl Durchläufe der Schleife


ldi R16,c1 ; Lade Register mit Schleifenwert
Loop: ; Schleifenbeginn
dec R16 ; Registerwert um Eins verringern
brne Loop ; wenn nicht Null dann Schleifenbeginn

Praktischerweise gibt die Konstante c1 die Anzahl Schleifendurchläufe direkt an. Mit ihr kann die
Anzahl der Durchläufe und damit die Verzögerung variiert werden. Da in ein 8-Bit-Register nur
Zahlen bis 255 passen, ist die Leistungsfähigkeit arg eng beschränkt.

Prozessortakte
Für die Zeitverzögerung mit einer solchen Schleife sind zwei Größen maßgebend:

● die Anzahl Prozessortakte, die die Schleife benötigt, und


● die Zeitdauer eines Prozessortakts.

Die Anzahl Prozessortakte, die die einzelnen Instruktionen benötigen, stehen in den Datenbüchern
der AVRs. Und zwar ziemlich weit hinten, unter "Instruction Set Summary", in der Spalte "#Clocks".
Demnach ergibt sich folgendes Bild:

.equ c1 = 200 ; 0 Takte, macht der Assembler alleine


ldi R16,c1 ; 1 Takt
Loop: ; Schleifenbeginn
dec R16 ; 1 Takt
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null

Damit setzt sich die Anzahl Takte folgendermaßen zusammen:

1. Laden: 1 Takt, Anzahl Durchläufe: 1 mal


2. Schleife mit Verzweigung an den Schleifenbeginn: 3 Takte, Anzahl Durchläufe: c1 - 1 mal
3. Schleife ohne Verzweigung an den Schleifenbeginn: 2 Takte, Anzahl Durchläufe: 1 mal

Damit ergibt sich die Anzahl Takte nt zu:

nt = 1 + 3*(c1-1) + 2

oder mit aufgelöster Klammer zu:

nt = 1 + 3*c1 - 3 + 2

oder halt noch einfacher zu:

nt = 3*c1

Jetzt haben wir die Anzahl Takte.

Taktfrequenz des AVR


Die Dauer eines Takts ergibt sich aus der Taktfrequenz des AVR. Die ist gar nicht so einfach zu
ermitteln, weil es so viele Möglichkeiten gibt, sie auszuwählen oder zu verstellen:

● AVRs ohne interne Oszillatoren: diese brauchen entweder


❍ einen externen Quarz,

❍ einen externen Keramikresonator, oder

❍ einen externen Oszillator

Die Taktfrequenz wird in diesem Fall von den externen Komponenten bestimmt.
● AVRs mit einem oder mehreren internen Oszillatoren: diese haben eine voreingestellte
Taktfrequenz, die im Kapitel "System Clock and Clock Options" bzw. im Unterkapitel
"Default Clock Source" steht. Jeder AVR-Typ hat da so seine besondere Vorliebe.
● AVRs mit internen RC-Oszillatoren bieten ferner die Möglichkeit, diesen zu verstellen. Dazu
werden Werte in den Port OSCCAL geschrieben. Bei älteren AVR geschieht das durch den
Programmierer, bei moderneren schreibt ein automatischer Mechanismus den OSCCAL-Wert
zu Beginn in den Port. Auch die Automatik benötigt den Handeingriff, wenn höhere
Genauigkeit gefordert ist und der AVR abseits der Spannung oder Betriebstemperatur
betrieben wird, für die er kalibriert ist (beim ATtiny13 z.B. 3 V und 25°C).
● Im Kapitel "System Clock and Clock Options" wird auch erklärt, wie man durch Verstellen
von Fuses
❍ zwischen internen und externen Taktquellen auswählt,

❍ einen internen Vorteiler zwischen Taktquelle und Prozessortakt schalten kann (Clock

Prescaler, siehe unten),


❍ eine Wartezeit beim Start des Prozessors einfügt, bis der Oszillator stabil schwingt

("Delay from Reset").


Die Fuses werden mittels Programmiergerät eingestellt. Obacht! Beim Verstellen von Fuses, z.
B. auf eine externe Taktquelle, muss diese auch angeschlossen sein. Sonst verabschiedet sich
der Prozessor absolut taktlos vom Programmiergerät und gibt diesem keine sinnvollen
Antworten mehr.
● Um das Publikum zu verwirren, haben einige AVR noch einen Vorteiler für den Prozessortakt
(Clock Prescaler). Dieser lässt sich entweder per Fuse (siehe oben) auf 1 oder 8 einstellen, bei
manchen AVR aber auch per Software auf Teilerwerte von 1, 2, 4, 8, bis 256 einstellen (Port
CLKPR).

Haben Sie aus all dem Durcheinander jetzt herausgefunden, mit wieviel MHz der AVR nun
eigentlich läuft (fc), dann ergibt sich die Dauer eines Prozessortakts (tc) zu:

tc [µs] = 1 / fc [MHz]

Bei 1,2 MHz Takt (ATtiny13, interner RC-Oszillator mit 9,6 MHz, CLKPR = 8) sind das z.B.
0,83 µs. Die restlichen Stellen können Sie getrost vergessen, der interne RC-Oszillator ist so arg
ungenau, dass weitere Stellen eher dem Glauben an Zauberei ähneln.

Zeitverzögerung
Mit der Anzahl Prozessortakte von oben (nc=3*c1, c1=200, nc=600) und 1,2 MHz Takt ergibt sich
eine Verzögerung von 500 µs. Mit maximal 640 µs ist die Maximalbegrenzung dieser Konstruktion
erreicht.

Verlängerung!
Mit folgendem Trick können Sie noch etwas Verlängerung herausholen:

.equ c1 = 200 ; 0 Takte, macht der Assembler alleine


ldi R16,c1 ; 1 Takt
Loop: ; Schleifenbeginn
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
dec R16 ; 1 Takt
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null

Jetzt braucht jeder Schleifendurchlauf (bis auf den letzten) acht Takte und es gelten folgende Formeln:

nc = 1 + 8*(c1 - 1) + 7

oder

nc = 8 * c1

Das verlängert die 8-Bit-Registerschleife immerhin auf 256 * 8 = 2048 Takte oder - bei 1,2 MHz -
auf ganze 1,7 ms.

Das Summprogramm
Immer noch nicht für die Blink-LED geeignet, aber immerhin
für ein angenehmes Brummen mit 586 Hz im Lautsprecher.
Schließen Sie einen Lautsprecher an Port B, Bit 0, an,
fairerweise über einen Elko von einigen µF, und lassen Sie das
folgende Programm auf den ATtiny13 los:

.inc "tn13def.inc" ; für einen ATtiny13


.equ c1 = 0 ; Bestimmt die Tonhöhe
sbi DDRB,0 ; Portbit ist Ausgang
Loop:
sbi PORTB,0 ; Portbit auf high
ldi R16,c1
Loop1:
nop
nop
nop
nop
nop
dec R16
brne Loop1
cbi PORTB,0 ; Portbit auf low
ldi R16,c1
Loop2:
nop
nop
nop
nop
nop
dec R16
brne Loop2
rjmp Loop

Gut brumm!

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/delay8.html1/20/2009 7:36:24 PM
Zeitschleifen in AVR Assembler

Path: Home => AVR-Überblick => Zeitschleifen => 16-Bit-Doppelregister

Zeitschleife mit 16-Bit-Doppelregister in


AVR Assembler
Hier wird eine 16-Bit-Zeitschleife mit einem Doppelregister erklärt. Mit dieser
können Verzögerungen um ca. eine halbe Sekunde realisiert werden. Damit wird eine
Blinkschaltung mit einer LED realisiert.

Code einer 16-Bit-Schleife


Eine Zeitschleife mit einem 16-Bit-Doppelregister sieht in Assembler folgendermaßen aus:

.equ c1 = 50000 ; Anzahl Durchläufe der Schleife


ldi R25,HIGH(c1) ; Lade MSB-Register mit Schleifenwert
ldi R24,LOW(c1) ; Lade LSB-Register mit Schleifenwert
Loop: ; Schleifenbeginn
sbiw R24,1 ; Doppelregisterwert um Eins verringern
brne Loop ; wenn nicht Null dann wieder Schleifenbeginn

Die Konstante c1 gibt wieder die Anzahl Schleifendurchläufe direkt an. Da in ein 16-Bit-Register
Zahlen bis 65535 passen, ist die Schleife 256 mal leistungsfähiger als ein einzelnes 8-Bit-Register.

Die Instruktion "SBIW R24,1" verringert das Doppelregister wortweise, d.h. nicht nur der Inhalt von
R24 wird um eins verringert, bei einem Unterlauf von R24 wird auch das nächsthöhere Register R25
um Eins verringert.

Das Doppelregister aus R24 und R25 (besser als R25:R24 benannt) eignet sich für solche Schleifen
besonders gut, weil die Doppelregister X (R27:R26), Y (R29:R28) und Z (R31:R30) neben den 16-
Bit-Operationen ADIW und SBIW auch noch andere Instruktionen kennen, und daher für den
schnöden Zweck einer Schleife zu schade sind und R25:R24 eben nur ADIW und SBIW können.

Prozessortakte
Die Anzahl Prozessortakte, die die einzelnen Instruktionen benötigen, steht wieder in den
Datenbüchern der AVRs. Demnach ergibt sich für die 16-Bit-Schleife folgendes Bild:

.equ c1 = 50000 ; 0 Takte, macht der Assembler alleine


ldi R25,HIGH(c1) ; 1 Takt
ldi R24,LOW(c1) ; 1 Takt
Loop: ; Schleifenbeginn
sbiw R24,1 ; 2 Takte
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null

Damit setzt sich die Anzahl Takte folgendermaßen zusammen:

1. Laden: 2 Takte, Anzahl Durchläufe: 1 mal


2. Schleife mit Verzweigung an den Schleifenbeginn: 4 Takte, Anzahl Durchläufe: c1 - 1 mal
3. Schleife ohne Verzweigung an den Schleifenbeginn: 3 Takte, Anzahl Durchläufe: 1 mal

Damit ergibt sich die Anzahl Takte nt zu:

nt = 2 + 4*(c1-1) + 3

oder mit aufgelöster Klammer zu:

nt = 2 + 4*c1 - 4 + 3

oder noch einfacher zu:

nt = 4*c1 + 1

Zeitverzögerung
Die Maximalzahl an Takten ergibt sich, wenn c1 zu Beginn auf 0 gesetzt wird, dann wird die Schleife
65536 mal durchlaufen. Maximal sind also 4*65536+1 = 262145 Takte Verzögerung möglich. Mit
der Anzahl Prozessortakte von oben (c1=50000, nc=4*c1+1) und 1,2 MHz Takt ergibt sich eine
Verzögerung von 166,7 ms.

Variable Zeitverzögerungen unterschiedlicher Länge sind manchmal nötig. Dies kann z.B. der Fall
sein, wenn die gleiche Software bei verschiedenen Taktfrequenzen laufen soll. Dann sollte die
Software so flexibel gestrickt sein, dass nur die Taktfrequenz geändert wird und sich die Zeitschleifen
automatisch anpassen. So ein Stück Software ist im Folgenden gezeigt. Zwei verschiedene
Zeitverzögerungen sind als Rechenbeispiele angegeben (1 ms, 100 ms).

;
; Verzoegerung 16-Bit mit variabler Dauer
;
.include "tn13def.inc"
;
; Hardware-abhaengige Konstante
;
.equ fc = 1200000 ; Prozessortakt (default)
;
; Meine Konstante
;
.equ fck = fc / 1000 ; Taktfrequenz in kHz
;
; Verzoegerungsroutine
;
Delay1ms: ; 1 ms Routine
.equ c1ms = (1000*fck)/4000 - 1 ; Konstante fuer 1 ms
ldi R25,HIGH(c1ms) ; lade Zaehler
ldi R24,LOW(c1ms)
rjmp delay
;
Delay100ms: ; 100 ms Routine
.equ c100ms = (100*fck)/4 - 1 ; Konstante fuer 100 ms
ldi R25,HIGH(c100ms) ; lade Zaehler
ldi R24,LOW(c100ms)
rjmp delay
;
; Verzoederungsschleife, erwartet Konstante in R25:R24
;
Delay:
sbiw R24,1 ; herunter zaehlen
brne Delay ; zaehle bis Null
nop ; zusaetzliche Verzoegerung

Hinweise: Die Konstanten c1ms und c100ms werden auf unterschiedliche Weise berechnet, um bei
der Ganzzahlen-Verarbeitung durch den Assembler einerseits zu große Rundungsfehler und
andererseits Überläufe zu vermeiden.

Verlängerung!
Mit folgendem Trick können Sie wieder etwas Verlängerung herausholen:

.equ c1 = 0 ; 0 Takte, macht der Assembler alleine


ldi R25,HIGH(c1) ; 1 Takt
ldi R24,LOW(c1) ; 1 Takt
Loop: ; Schleifenbeginn
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
nop ; tue nichts, 1 Takt
sbiw R24 ; 2 Takte
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null

Jeder Schleifendurchlauf (bis auf den letzten) braucht jetzt zehn Takte und es gelten folgende
Formeln:

nc = 2 + 10*(c1 - 1) + 9

oder

nc = 10 * c1 + 1

Maximal sind jetzt 655361 Takte Verzögerung möglich

Das Blinkprogramm
Damit sind wir beim beliebten "Hello World" für AVRs: der im
Sekundenrhytmus blinkenden LED an einem AVR-Port. Die
Hardware, die es dazu braucht, ist bescheiden. Die Software steht da:

.inc "tn13def.inc" ; für einen ATtiny13


.equ c1 = 60000 ; Bestimmt die Blinkfrequenz
sbi DDRB,0 ; Portbit ist Ausgang
Loop:
sbi PORTB,0 ; Portbit auf high
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop1:
nop
nop
nop
nop
nop
sbiw R24,1
brne Loop1
cbi PORTB,0 ; Portbit auf low
ldi R25,HIGH(c1)
ldi R24,LOW(c1)
Loop2:
nop
nop
nop
nop
nop
sbiw R24,1
brne Loop2
rjmp Loop

Gut blink!

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/delay16.html1/20/2009 7:36:27 PM
http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/speaker.gif

http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/speaker.gif1/20/2009 7:36:28 PM
http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/led.gif

http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/led.gif1/20/2009 7:36:30 PM
Interruptprogrammierung in AVR Assembler

Path: Home => AVR-Überblick => Interrupt-Programmierung

Interruptprogrammierung in
AVR Assembler
Bevor man seine ersten Programme mit Interrupt-Steuerung
programmiert, sollte man das hier alles gelesen, verstanden
und verinnerlicht haben. Auch wenn das einigen Aufwand
bedeutet: es zahlt sich schnell aus, weil es viel Frust
vermeidet.

Überblick
1. Interrupt-Vektoren,
2. Interruptquellen,
3. Ablauf im Programm,
4. Interrupts und Ressourcen.

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/interrupts/index.html1/20/2009 7:36:35 PM
Interruptprogrammierung in AVR Assembler

Path: Home => AVR-Überblick => Interrupt-Programmierung => Vektortabelle

Die Interrupt-Vektoren-
Tabelle

Hier kommt alles über die Reset- und Interrupt-Vektoren-Tabelle, und was man bei ihr richtig und
falsch machen kann.

Wat is ene Vektortabelle?


Vergessen Sie für eine Weile mal die Worte Vektor und Tabelle, sie haben hier erst mal nix zu sagen
und dienen nur der Verwirrung des unkundigen Publikums. Wir kommen auf die zwei Worte aber
noch ausführlich zurück.

Stellen Sie sich einfach vor, dass jedes Gerät im AVR für jede Aufgabe, die einer Unterbrechung des
Prozessors würdig ist, eine feste Adresse hat, zu der sie den Prozessor zwingt hinzuspringen, wenn
das entsprechende Ereignis eintritt (also z.B. der Pegel an einem INT0-Eingang wechselt oder wenn
der Timer gerade eben übergelaufen ist). Der Sprung an genau diese eine Adresse ist in jedem AVR
für jedes Gerät und jedes Ereignis festgenagelt. Welche Adresse mit welchem Gerät und Ereignis
verknüpft ist, steht im Handbuch für den jeweiligen AVR-Typ. Oder ist in Tabellen hier aufgelistet.

Alle Interrupt-Sprungziele sind am Anfang des Programmspeichers, beginned bei der Adresse 0000
(mit dem Reset), einfach aufgereiht. Es sieht fast aus wie eine Tabelle, es ist aber gar keine wirkliche.
Eine Tabelle wäre, wenn an dieser Adresse tatsächlich das eigentliche Sprungziel selbst stünde, z.B.
eine Adresse, zu der jetzt weiter verzweigt werden soll. Der Prozessor täte diese dort abholen und den
aus der Tabelle ausgelesenen Wert in seinen Programmzähler laden. Wir hätten dann eine echte Liste
mit Adressen vor uns, eine echte Tabelle.

Beim AVR gibt es aber gar keine solche Tabelle mit Adresswerten. Stattdessen stehen in unserer
sogenannten Tabelle Sprungbefehle wie RJMP herum. Der AVR ist also noch viel einfacher
gestrickt: wenn ein INT0-Interrupt auftritt, lädt er einfach die Adresse 0001 in seinen
Programmspeicher und führt den dort stehenden Befehl aus. Und das MUSS dann eben ein
Sprungbefehl an die echte Adresse sein, an der auf den Interrupt reagiert wird, die Interrupt-Service-
Routine (ISR).

Also nix Tabelle, sondern Auflistung der Sprungbefehle zu den Serviceroutinen. Jetzt haben wir noch
die Sache mit dem Vektor zu klären. Auch dieses Wort ist Käse und hat mit den AVRs rein gar nix zu
tun. Als man noch Riesen-Mikrocomputer baute mit etlichen 40-poligen ICs, die als Timer, UARTs
und I/O-Ports nach außen hin die Schnittstellenarbeit verrichteten, fand man es eine gute Idee, wenn
diese selbst darüber bestimmen könnten, wo ihre Service-Routine im Programmspeicher zu finden
ist. Sie gaben dazu bei einem Interrupt einen Wert an den Prozessor, der dann diesen zu einer
Tabellen-Anfangsadresse addierte und die Adresse der Service-Routine von dieser Adresse holte. Das
war sehr flexibel, weil man sowohl die Tabelle als auch die vom Schnittstellenbaustein
zurückgegebenen Werte jederzeit im Programm manipulieren konnte und so flugs die ganze Tabelle
oder die Interrupt-Service-Routine wechseln konnte. Der zu der Tabellenadresse zu zählende Wert
wurde als Vektor oder Displacement (Verschiebung) bezeichnet.

Und jetzt wissen wir, wie es zu dem Wort Vektortabelle kam, und dass es mit den AVR rein gar nix
zu tun hat, weil wir es weder mit einer Tabelle noch mit Vektoren zu tun haben. Unsere Sprungziele
sind im AVR fest verdrahtet, es wird auch nix zu einer Anfangsadresse einer Tabelle addiert und
schon gar nicht sind irgendwelche Service-Routinen austauschbar.

Warum verwenden wir diese Worte überhaupt? Gute Frage. Weil es alle tun, weil es sich doll anhört
und weil es Anfänger eine Weile davon abhält zu kapieren worum es wirlich geht.

Aussehen bei kleinen AVR


Eine Reset- und Interrupt-Vektor-Tabelle sieht bei einem kleineren AVR folgendermaßen aus:

rjmp Main ; Reset, Sprung zur Initiierung


rjmp Int0Sr ; Externer Interrupt an INT0, Sprung zur Service-
Routine
reti ; Irgendein anderer Interrupt, nicht benutzt
rjmp IntTc0OvflwSr ; Überlauf Timer 0, Behandlungsroutine
reti ; Irgendwelche anderen Interrupts, nicht benutzt
reti ; Und noch mehr Interrupts, auch nicht benutzt

Merke:

● Die Anzahl der Instruktionen (RJMP, RETI) hat exakt der Anzahl der im jeweiligen AVR-Typ
möglichen Interrupts zu entsprechen.
● Alle benutzten Interrupts verzweigen mit RJMP zu einer spezifischen Interrupt-Service-
Routine.

● Alle nicht benutzten Interrupt-Sprungadressen werden mit der Instruktion RETI abgeschlossen.

Alles andere hat in dieser Sprungliste rein gar nix zu suchen. Das hat damit zu tun, dass die
Sprungadressen dann genau stimmen, kein Vertun beim Springen erfolgt und die korrekte Anzahl
und Abfolge mit dem Handbuch verglichen werden kann. Die Instruktion RETI sorgt dafür, dass der
Stapel in Ordnung gebracht wird und Interrupts auf jeden Fall wieder zugelassen werden.

Schlaumeier glauben, sie könnten auf die lästigen RETI-Instruktionen verzichten. Z.B. indem sie das
oben stehende wie folgt formulieren:

rjmp Main ; Reset, Sprung zur Initiierung


.org $0001
rjmp Int0Sr ; Externer Interrupt an INT0, Sprung zur Service-
Routine
.org $0003
rjmp IntTc0OvflwSr ; Überlauf Timer 0, Behandlungsroutine

Das geht, alle Sprungbefehle stehen an der korrekten Position. Es


funktioniert auch, solange nicht absichtlich oder aus Versehen ein
weiterer Interrupt zugelassen wird. Der ungeplante Interrupt findet
an der mit .org übersprungenen Stelle den auszuführenden Opcode
$FFFF vor, da alle unprogrammierten Speicherstellen des
Programmspeichers beim Löschen mit diesem befüllt werden. Dieser
Opcode ist nirgendwo definiert, er macht auch nix, er bewirkt
nichts und die Bearbeitung wird einfach an der nächsten Stelle im
Speicher fortgesetzt. Wo der versehentliche Interrupt landet, ist
dann recht zufällig und jedenfalls ungeplant. Folgt auf die
Einsprungstelle irgendwo noch ein weiterer Sprung zu einer anderen
Serviceroutine, dann wird eben die fälschlich ausgeführt. Folgt
keine mehr, dann läuft das Programm in die nächstfolgende
Unterroutine. Das wäre fatal, weil die garantiert nicht mit RETI
endet und daher die Interrupts nie wieder zugelassen werden. Oder,
wenn keine Unterroutinen zwischen der Sprungtabelle und dem
Hauptprogramm stehen, der weitere Ablauf läuft in das
Hauptprogramm, und alles wird wieder von vorne initiiert.

Ein weiteres Scheinargument, damit liefe die Software auf jedem


anderen AVR-Typ auch korrekt, ist ebenfalls Käse. Ein Blick auf die
Tabellen mit den Interrupt-Sprungzielen zeigt, dass sich ATMEL
mitnichten immer an irgendwelche Reihenfolgen gehalten hat und dass
es munter durcheinander geht. Die Scheinkompatibilitäet kann also
zur Nachlässigkeit verführen, eine fatale Fehlerquelle.

Daher sollte gelten:

● In einer Sprungtabelle haben .org-Direktiven nix verloren.


● Jeder (noch) nicht verwendete Eintrag in der Sprungtabelle wird mit RETI abgeschlossen.
● Die Länge der Sprungtabelle entspricht exakt der für den Prozessor definierten Anzahl
Interruptsprünge.

Aufbau bei großen AVR


Große AVR haben einen Adressraum, der mit relativen Sprungbefehlen nicht mehr ganz zugänglich
ist. Bei diesen hat die Sprungliste Einträge mit jeweils zwei Worten Länge. Etwa so:

jmp Main ; Reset, Sprung zur Initiierung


jmp Int0Sr ; Externer Interrupt an INT0, Sprung zur Service-
Routine
reti ; Irgendein anderer Interrupt, nicht benutzt
nop
jmp IntTc0OvflwSr ; Überlauf Timer 0, Behandlungsroutine
reti ; Irgendwelche anderen Interrupts, nicht benutzt
nop
reti ; Und noch mehr Interrupts, auch nicht benutzt
nop

Bei Ein-Wort-Einträgen (z.B. RETI) sind die NOP-Instruktionen


eingefügt, um ein weiteres Wort zu ergänzen, damit die Adressierung
der nachfolgenden Sprungziel-Einträge wieder stimmt.

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_vektor.html1/20/2009 7:36:37 PM
Interruptprogrammierung in AVR Assembler

Path: Home => AVR-Überblick => Interrupt-Programmierung => Quellen

Interruptprogrammierung in AVR Assembler

Hier wird erläutert, von welchen Quellen aus Interrupts ausgelöst werden können.

Quellen von Interrupts


Generell gilt:

● Jeder AVR-Typ verfügt über unterschiedliche Hardware und kann daher auch unterschiedliche Arten an Interrupts auslösen.

● Ob und welche Interrupts implementiert sind, ist aus dem jeweiligen Datenbuch für den AVR-Typ zu entnehmen.
● Die Interruptquellen bei jedem Typ sind priorisiert, d.h. bei gleichzeitig auftretender Interruptanforderung wird der Interrupt mit der höheren Priorität zuerst
bearbeitet.

Arten Hardware-Interrupts

Bei den folgenden Tabellen bedeutet ein kleines n eine Ziffer, die Zählung beginnt immer mit 0. Die Benennung der Interrupts in den Handbüchern sind uneinheitlich, die
Abkürzungen für die Benennung der Interrupts wurden für eine übersichtliche Darstellung gewählt und sind nicht offiziell.

Folgende hauptsächlichen Interrupts sind zu unterscheiden. Aufgelistet ist die Hardware, wann ein Interrupt erfolgt, Erläuterungen dazu, die Verfügbarkeit der Interruptart
bei den AVR-Typen und der Name, unter dem der Interrupt in den folgenden Tabellen gefunden wird.
Gerät Interrupt bei ... Erläuterung Verfügbarkeit Name(n)
Wählbar, ob jeder Pegelwechsel, nur solche von Low auf high oder INT0 bei allen
Pegelwechseln an einem bestimmten Portanschluss
Externe Interrupts nur solche von High auf Low einen Interrupt auslösen können (ISC- viele haben INT1 INTn
(INTn)
Bits). wenige INT2
Wählbar mit Maske, welche Bits bei Pegelwechsel einen Interrupt bei vielen
Port Interrupts Pegelwechsel an einem Port (PCIn) PCIn
auslösen tiny/mega
Timer überschreitet seinen Maximalwert und beginnt bei Null; bei
Überlauf 8-Bit-Timern 256, bei 16-Bit-Timern 65536, bei CTC auch der im bei allen Timern TCnO
Compare-Register A eingestellte Maximalwert
bei Timern mit nur einem Vergleichswert: Übereinstimmung mit
Vergleichswert viele TCnC
Timer Interrupts COMP-Wert erreicht
Vergleichs- bei Timern mit mehreren Vergleichswerten: Übereinstimmung mit A,B: viele TCnA...
werte A, B, C COMP-Wert erreicht C wenige TCnC
bei Timer im Zählmodus: Übereinstimmung der gezählten Impulse
Fangwert viele TCnP
mit CAPT-Wert erreicht
Zeichen ein vollständiges Zeichen wurde empfangen und liegt im
viele UnRX
empfangen Eingangspuffer
Senderegister
UART Zeichen in Sendepuffer übernommen, frei für nächstes Zeichen viele UnUD
frei
Senden
letztes Zeichen fertig ausgesendet, Senden beendet viele UnTX
beendet
EEPROM Schreibvorgang im EEPROM ist beendet, der nächste fast
EEPROM EERY
ready Schreibvorgang kann begonnen werden alle
Wandlung eine Umwandlung der Eingangsspannung ist erfolgt, der alle
ADC ADC
komplett Ergebniswert kann vom Datenregister abgeholt werden mit ADC
Wechsel
Analog je nach Einstellung der ACIS-Bits erfolgt ein Interrupt bei jedem ANA
bei alle
Komparator Polaritätätswechsel oder nur bei positiven bzw. negativen Flanken ANAn
Vergleich
Weitere (diverse) (weitere Interrupt-Arten sind den Handbüchern zu entnehmen) einige
Jeder dieser Interrupts ist per Software ein- und ausschaltbar, auch während des Programmablaufs. Die Voreinstellung beim RESET ist, dass keiner dieser Interrupts
ermöglicht ist.

To the top of that page

AVR-Typen mit Ein-Wort-Vektoren

Bedingt durch die unterschiedliche Ausstattung der AVR-Typen mit internem SRAM ist bei den AVR-Typen die Interrupt-Vektoren-Tabelle entweder auf Ein-Wort-
(RJMP) oder Zwei-Wort-Instruktionen (JMP) ausgelegt. AVR-Typen mit wenig SRAM kommen mit einem relativen Sprung aus und benötigen daher ein Wort pro Vektor.
Jedes Programmwort in der Tabelle entspricht genau einem Interrupt.

In der folgenden Tabelle sind die AVR-Typen mit ihren Interrupts aufgelistet. Die Adressen geben an, an welcher Stelle der Tabelle der Vektor liegt. Sie geben gleichzeitig
die Priorität an: je niedriger die Adresse desto höher der Vorrang des Interrupts. Leere Kästen geben an, dass dieser Vektor nicht verfügbar ist.
Typ/Adr 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A 000B 000C 000D 000E 000F 0010 0011 0012 0013 0014
AT90S1200 RES INT0 TC0O ANA
AT90S2313 RES INT0 INT1 TC1P TC1C TC1O TC0O U0RX U0UD U0TX ANA
AT90S2323 RES INT0 TC0O
AT90S2343 RES INT0 TC0O
AT90S4433 RES INT0 INT1 TC1P TC1C TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY ANA
AT90S4434 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY ANA
AT90S8515 RES INT0 INT1 TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ANA
AT90S8535 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY ANA
ATmega8 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TWI SPMR
ATmega8515 RES INT0 INT1 TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ANA INT2 TC0C EERY SPMR
ATmega8535 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TWI INT2 TC0C SPMR
ATtiny11 RES INT0 PCI0
ATtiny12 RES INT0 PCI0
ATtiny13 RES INT0 PCI0 TC0O EERY ANA TC0A TC0B WDT ADC
ATtiny15L RES INT0 PCI0 TC1A TC1O TC0O EERY ANA ADC
ATtiny22 RES INT0 TC0O
ATtiny24 RES INT0 PCI0 PCI1 WDT TC1P TC1A TC1B TC1O TC0A TC0B TC0O ANA ADC EERY USIS USIO
ATtiny25 RES INT0 PCI0 TC1A TC1O TC0O EERY ANA ADC TC1B TC0A TC0B WDT USIS USIO
ATtiny26 RES INT0 PCI0 TC1A TC1B TC1O TC0O USIS USIO EERY ANA ADC
ATtiny28 RES INT0 INT1 PCI0 TC0O ANA
ATtiny44 RES INT0 PCI0 PCI1 WDT TC1P TC1A TC1B TC1O TC0A TC0B TC0O ANA ADC EERY USIS USIO
ATtiny45 RES INT0 PCI0 TC1A TC1O TC0O EERY ANA ADC TC1B TC0A TC0B WDT USIS USIO
ATtiny84 RES INT0 PCI0 PCI1 WDT TC1P TC1A TC1B TC1O TC0A TC0B TC0O ANA ADC EERY USIS USIO
ATtiny85 RES INT0 PCI0 TC1A TC1O TC0O EERY ANA ADC TC1B TC0A TC0B WDT USIS USIO
ATtiny261 RES INT0 PCI0 TC1A TC1B TC1O TC0O USIS USIO EERY ANA ADC WDT INT1 TC0A TC0B TC0P TC1D FAUL
ATtiny461 RES INT0 PCI0 TC1A TC1B TC1O TC0O USIS USIO EERY ANA ADC WDT INT1 TC0A TC0B TC0P TC1D FAUL
ATtiny861 RES INT0 PCI0 TC1A TC1B TC1O TC0O USIS USIO EERY ANA ADC WDT INT1 TC0A TC0B TC0P TC1D FAUL
ATtiny2313 RES INT0 INT1 TC1P TC1A TC1O TC0O U0RX U0UD U0TX ANA PCI0 TC1B TC0A TC0B USIS USIO EERY WDTO
Man beachte, dass

● Arten und Reihenfolgen der Interrupts nur bei einigen wenigen Typen gleich sind,
● bei Umstellung von einem auf einen anderen Prozessor in der Regel die gesamte Vektortabelle umgestellt werden muss.

To the top of that page

AVR-Typen mit Zwei-Wort-Vektoren

Bei AVR-Typen mit größerem SRAM kann ein Teil des verfügbaren Programmraums mit relativen Sprungbefehlen wegen der begrenzten Sprungdistanz nicht mehr erreicht
werden. Diese Typen verwenden daher pro Vektor zwei Speicherworte, so dass der absolute Sprungbefehl JMP verwendet werden kann, der zwei Worte einnimmt.

Die folgenden Tabellen listen die bei diesen AVR-Typen verfügbaren Interrupts auf. Da die Anzahl an Vektoren sehr groß ist, ist die Tabelle in jeweils 16 Vektoren
unterteilt.
AVR-Typ/Adr 0000 0002 0004 0006 0008 000A 000C 000E 0010 0012 0014 0016 0018 001A 001C 001E
AT90CAN32 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1C TC1O
AT90CAN64 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1C TC1O
AT90CAN128 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1C TC1O
ATmega16 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY
ATmega32 RES INT0 INT1 INT2 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega48 RES INT0 INT1 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O TC0A TC0B
ATmega64 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1O TC0C
ATmega88 RES INT0 INT1 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O TC0A TC0B
ATmega103 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1O TC0C
ATmega128 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TC2C TC2O TC1P TC1A TC1B TC1O TC0C
ATmega161 RES INT0 INT1 INT2 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U1RX U0UD
ATmega162 RES INT0 INT1 INT2 PCI0 PCI1 TC3P TC3A TC3B TC3O TC2C TC2O TC1P TC1A TC1B TC1O
ATmega163 RES INT0 INT1 TC2C TC2O TC1P TC1A TC1B TC1O TC0O SPIS U0RX U0UD U0TX ADC EERY
ATmega164 RES INT0 INT1 INT2 PCI0 PCI1 PCI2 PCI3 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O
ATmega165 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega168 RES INT0 INT1 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O TC0A TC0B
ATmega169 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
AVR-Typ/Adr 0000 0002 0004 0006 0008 000A 000C 000E 0010 0012 0014 0016 0018 001A 001C 001E
ATmega323 RES INT0 INT1 INT2 TC2C TC20 TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega324 RES INT0 INT1 INT2 PCI0 PCI1 PCI2 PCI3 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O
ATmega325 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega329 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega406 RES BATI INT0 INT1 INT2 INT3 PCI0 PCI1 WDT WAKE TC1C TC1O TC0A TC0B TC0O TWBU
ATmega640 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O
ATmega644 RES INT0 INT1 INT2 PCI0 PCI1 PCI2 PCI3 WDT TC2A TC2B TC2O TC1P TC1A TC1B TC1O
ATmega645 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega649 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega1280 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O
ATmega1281 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O
ATmega2560 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O
ATmega2561 RES INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 PCI0 PCI1 PCI2 WDT TC2A TC2B TC2O
ATmega3250 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega3290 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega6450 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX
ATmega6490 RES INT0 PCI0 PCI1 TC2C TC2O TC1P TC1A TC1B TC1O TC0C TC0O SPIS U0RX U0UD U0TX

To the top of that page

Interrupts mit den Vektoren von 0020 bis 003E:


AVR-Typ/Adr 0020 0022 0024 0026 0028 002A 002C 002E 0030 0032 0034 0036 0038 003A 003C 003E
AT90CAN32 TC0C TC0O CANI OVRI SPIS U0RX U0UD U0TX ANAC ADC EERY TC3P TC3A TC3B TC3C TC3O
AT90CAN64 TC0C TC0O CANI OVRI SPIS U0RX U0UD U0TX ANAC ADC EERY TC3P TC3A TC3B TC3C TC3O
AT90CAN128 TC0C TC0O CANI OVRI SPIS U0RX U0UD U0TX ANAC ADC EERY TC3P TC3A TC3B TC3C TC3O
ATmega16 ANA TWI INT2 TC0C SPMR
ATmega32 ADC EERY ANA TWI SPMR
ATmega48 TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TWI SPMR
ATmega64 TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TC1C TC3P TC3A TC3B TC3C TC3O U1RX U1UD
ATmega88 TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TWI SPMR
ATmega103 TC0O SPIS U0RX U0UD U0TX ADC EERY ANA
ATmega128 TC0O SPIS U0TX U0UD U0TX ADC EERY ANA TC1C TC3P TC3A TC3B TC3C TC3O U1RX U1UD
ATmega161 U1UD U0TX U1TX EERY ANA
ATmega162 TC0C TC0O SPIS U0RX U1RX U0UD U1UD U0TX U1TX EERY ANA SPMR
ATmega163 ANA TWI
ATmega164 TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TWI
ATmega165 USIS USIO ANA ADC EERY SPMR
ATmega168 TC0O SPIS U0RX U0UD U0TX ADC EERY ANA TWI SPMR
ATmega169 USIS USIO ANA ADC EERY SPMR LCD
AVR-Typ/Adr 0020 0022 0024 0026 0028 002A 002C 002E 0030 0032 0034 0036 0038 003A 003C 003E
ATmega323 ADC EERY ANA TWSI
ATmega324 TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TWI
ATmega325 USIS USIO ANA ADC EERY SPMR
ATmega329 USIS USIO ANA ADC EERY SPMR LCD
ATmega406 TWI VADC CADC CADR EERY SPMR
ATmega640 TC1P TC1A TC1B TC1C TC1O TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TC3P
ATmega644 TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TWI
ATmega645 USIS USIO ANA ADC EERY SPMR
ATmega649 USIS USIO ANA ADC EERY SPMR LCD
ATmega1280 TC1P TC1A TC1B TC1C TC1O TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TC3P
ATmega1281 TC1P TC1A TC1B TC1C TC1O TC0A TC0B TC0O SPIS U0TX U0UD U0TX ANA ADC EERY TC3P
ATmega2560 TC1P TC1A TC1B TC1C TC1O TC0A TC0B TC0O SPIS U0RX U0UD U0TX ANA ADC EERY TC3P
ATmega2561 TC1P TC1A TC1B TC1C TC1O TC0A TC0B TC0O SPIS U0TX U0UD U0TX ANA ADC EERY TC3P
ATmega3250 USIS USIO ANA ADC EERY SPMR PCI2 PCI3
ATmega3290 USIS USIO ANA ADC EERY SPMR LCD PCI2 PCI3
ATmega6450 USIS USIO ANA ADC EERY SPMR PCI2 PCI3
ATmega6490 USIS USIO ANA ADC EERY SPMR LCD PCI2 PCI2

To the top of that page

Vektoren mit Adressen 0040 bis 005F:


AVR-Typ/Adr 0040 0042 0044 0046 0048 004A 004C 004E 0050 0052 0054 0056 0058 005A 005C 005E
AT90CAN32 U1RX U1UD U1TX TWI SPMR
AT90CAN64 U1RX U1UD U1TX TWI SPMR
AT90CAN128 U1RX U1UD U1TX TWI SPMR
ATmega64 U1TX TWI SPMR
ATmega128 U1TX TWI SPMR
ATmega1280 TC3A TC3B TC3C TC3O U1RX U1UD U1TX TWI SPMR TC4P TC4A TC4B TC4C TC4O TC5P TC5A
ATmega1281 TC3A TC3B TC3C TC3O U1RX U1UD U1TX TWI SPMR TC4P TC4A TC4B TC4C TC4O TC5P TC5A
ATmega2560 TC3A TC3B TC3C TC3O U1RX U1UD U1TX TWI SPMR TC4P TC4A TC4B TC4C TC4O TC5P TC5A
ATmega2561 TC3A TC3B TC3C TC3O U1RX U1UD U1TX TWI SPMR TC4P TC4A TC4B TC4C TC4O TC5P TC5A

Vektoren mit Adressen 0060 bis 0070:


AVR-Typ/Adr 0060 0062 0064 0066 0068 006A 006C 006E 0070
ATmega1280 TC5B TC5C TC5O U2RX U2UD U2TX U3RX U3UD U3TX
ATmega1281 TC5B TC5C TC5O
ATmega2560 TC5B TC5C TC5O U2RX U2UD U2TX U3RX U3UD U3TX
ATmega2561 TC5B TC5C TC5O

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_quellen.html1/20/2009 7:36:42 PM
Interruptprogrammierung in AVR Assembler

Path: Home => AVR-Überblick => Interrupt-Programmierung => Ablauf

Interruptprogrammierung in AVR
Assembler
Hier wird erläutert, wie interrupt-gesteuerte Programme grundsätzlich ablaufen
müssen. Um das Prinzip zu verdeutlichen, wird zuerst ein einfacher Ablauf
demonstriert. Dann wird gezeigt, was sich bei mehreren Interrupts ändert.

Warnung! Hier gibt es ein Konzept zu erlernen!


Für alle, die bisher nur in Hochsprachen oder, in Assembler, nur schleifengesteuerte Programme gebaut haben, hier eine
wichtige Warnung. Das Folgende wirft einiges Gewohntes über Programmierung über den Haufen. Mit den gewohnten
Schemata im Kopf ist das Folgende schlicht nicht zu kapieren. Lösen Sie sich von dem Gewohnten und stellen Sie
ausschließlich die Interrupts in den Vordergrund. Um diese dreht sich bei dieser Programmierung nun alles. Das heißt, er ist
unser Ausgangspunkt für so ziemlich alles:

● mit ihm beginnt jeder Ablauf,


● er steuert alle Folgeprozesse,
● sein Wohlergehen (Funktionieren, Eintreten, rechtzeitige Bearbeitung, etc.) ist alleroberste Maxime,
● alle anderen Programmteile horchen auf seinen Eintritt und sind reine Sklaven und Zulieferanten des Masters
Interrupt.

Wenn Sie Schwierigkeiten und Unwohlsein beim Kapieren des Konzepts verspüren, versuchen Sie aus dem ungewohnten
Dilemma auch nicht den Ausweg, in alte Strukturen zu verfallen. Ich garantiere Ihnen, dass eine Mischung aus Interrupts
und gewohntem linearen Programmieren am Ende viel komplizierter ist als das neue Konzept in seiner Reinform
anzuwenden: sie verheddern sich in diversen Schleifen, der nächste Interrupt kommt bestimmt, aber ob Ihr Hauptprogramm
auf ihn hört, bleibt ein Rätsel.

Wenn Sie das Interrupt-Konzept verinnerlicht haben, geht alles viel leichter und eleganter. Und garantiert noch schneller und
eleganter als in der Hochsprache, die solche netten Erfindungen vor Ihnen verheimlicht, sie in vorgefertigte und oft
unpassende Korsette einschnürt, so dass Sie die wahre Vielfalt des Möglichen gar nicht erst zu Gesicht bekommen.

Ablauf eines interruptgesteuerten Programms


Den Standardablauf eines interrupt-gesteuerten Propgrammes in allgemeiner Form zeigt das folgende Bild.

Reset, Init

Nach dem Einschalten der Betriebsspannung beginnt der Prozessorstart immer bei der Adresse 0000. An dieser Adresse
MUSS ein Sprungbefehl an die Adresse des Hauptprogrammes stehen (in der Regel RJMP, bei großen ATmega kann auch
JMP verwendet werden).
Das Hauptprogramm setzt zu allererst die Stapeladresse in den bzw. die Stapelzeiger, weil alle interruptgesteuerten
Programme den Stapel ZWINGEND benötigen. Dann initiiert das Hauptprogramm die Hardware, schaltet also Timer, AD-
Wandler, Serielle Schnittstelle und was auch immer gebraucht wird ein und ermöglicht die entsprechenden Interrupts.
Außerdem werden dann noch Register mit ihren richtigen Startwerten zu laden, damit alles seinen geregelten Gang geht.
Dann ist noch wichtig, den Schlafmodus so zu setzen, dass der Prozessor bei Interrupts auch wieder aufwacht. Am Ende
wird das Interrupt-Flag des Prozessors gesetzt, damit er auch auf ausgelöste Interrupts reagieren kann. Damit ist alles
erledigt und der Prozessor wird mit der Instruktion SLEEP schlafen gelegt.

Interrupt

Irgendwann schlägt nun Interrupt 3 zu. Der Prozessor

● wacht auf,
● schaltet die Interrupts ab,
● legt den derzeitigen Wert des Programmzählers (die nächste Instruktion hinter SLEEP) auf dem Stapel ab,
● schreibt die Adresse 0003 in den Programmzähler, und
● setzt die Verarbeitung an dieser Adresse fort,
● dort steht ein Sprungbefehl zur Interrupt-Service-Routine an Adresse ISR3:,
● ISR3: wird bearbeitet und signalisiert durch Setzen von Bit 4 in einem Flaggenregister, dass eine Weiterverarbeitung
des Ereignisses notwendig wird,
● ISR3 wird beendet, indem mit der Instruktion RETI die Ausgangsadresse vom Stapel geholt und in den
Programmzähler geladen wird und schließlich die Interrupts wieder zugelassen werden,
● der nun aufgeweckte Prozessor setzt die Verarbeitung an der Instruktion hinter SLEEP fort,
● falls ISR3 das Flaggenbit gesetzt hat, kann jetzt die Nachbearbeitung des Ereignisses erfolgen und das Flaggenbit
wieder auf Null gesetzt werden,
● ohne oder mit Nachbearbeitung wird der Prozessor auf jeden Fall wieder schlafen gelegt.

Der Ablauf zeigt, wie die Interrupt-Service-Routine mit dem Rest des Programmablaufs kommuniziert: über das Flaggenbit
wird mitgeteilt, dass etwas Weiteres zu tun ist, was nicht innerhalb der Service-Routine erledigt wurde (z.B. weil es zu lange
dauern würde, zu viele Resourcen benötigt, etc.).

Ablauf bei mehreren interruptgesteuerten Abläufen


Sind mehrere
Interrupts aktiv,
beginnt der
Programmablauf
genauso und
auch alle
weiteren
Abläufe sind
ganz ähnlich.
Durch die Wahl
der Reihenfolge
der
Nachbearbeitung
lässt sich
steuern, welche
zuerst fertig ist.

Das Schema
lässt sich leicht
um weitere
Interrupts und
deren
Nachbearbeitung
erweitern. Das
Ganze funktioniert nur, wenn die Interrupt-Service-Routinen kurz sind und sich nicht gegenseitig blockieren und behindern.

Bei zunehmendem Zeitbedarf und vielen rasch aufeinander folgenden Interrupts sind sorgfältige Überlegungen zum Timing
wichtig. Folgen zwei Setzvorgänge im Flaggenregister zu rasch aufeinander und dauert die Nachbearbeitung zu lange, würde
ein Ereignis verpasst. Man muss dann andere Wege versuchen, die Lasten bei der Bearbeitung zu verteilen.

Man erkennt hier nebenbei die Zentrierung des gesamten Programmablaufes auf die Interrupts. Sie sind die zentrale
Steuerung.

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ablauf.html1/20/2009 7:36:52 PM
Interruptprogrammierung in AVR Assembler

Path: Home => AVR-Überblick => Interrupt-Programmierung => Interrupts und Ressourcen

Interrupts und Ressourcen


Interrupts haben den Vorteil, dass sie nur dann auftreten und
bearbeitet werden müssen, wenn ein bestimmtes Ereignis
tatsächlich eintritt. Selten ist vorhersagbar, wann das
Ereignis genau eintreten wird. Sogar mehrere
unterschiedliche Ereignisse können gleichzeitig oder kurz
hintereinander eintreten. Zum Beispiel kann der Timer
gerade einen Overflow haben und der AD-Wandler ist gerade
mit einer Messumwandlung fertig. Diese Eigenart, dass sie
jederzeit auftreten können, macht einige besondere
Überlegungen beim Programmieren erforderlich, die in
Hochsprachen entweder nicht vorkommen oder vom Compiler eigenständig erledigt werden. In
Assembler müssen wir selber denken, und werden dafüfür mit einem schlanken, sauschnellen und
zuverlässigen Programm belohnt. Die folgenden Überlegungen nimmt uns Assembler-
Programmierern keiner ab.

Klare Ressourcenzuordnung

Das Statusregister als sensible Ressource

Das Zuschlagen eines Interrupts kann jederzeit und überall, nur nicht innerhalb von Interrupt-Service-
Routinen erfolgen. Erfolgt innerhalb der Service-Routine eine Beeinflussung von Flaggen des
Statusregisters, was nahezu immer der Fall ist, dann kann das im Hauptprogramm-Loop üble Folgen
haben. Plötzlich ist das Zero- oder Carry-Flag im Statusregister gesetzt, nur weil zwischendurch der
Interrupt zuschlug. Nichts funktioniert mehr so, wie man es erwartet hat. Aber das nur machmal und
nicht immer. Ein solches Programm verhält sich eher wie ein Zufallsgenerator als wie ein
zuverlässiges Stück Software.

AVR-Prozessoren haben keinen zweiten Satz Statusregister, auf den sie bei einem Interrupt
umschalten können. Deshalb muss das Statusregister vor einer Veränderung in der Interrupt-Service-
Routine gesichert und vor deren Beendigung wieder in seinen Originalzustand versetzt werden. Dazu
gibt es drei Möglichkeiten:
Zeitbedarf
Nr. Sicherung in Code Vorteile Nachteile
Takte
in R15,SREG
Register-
1 Register [...] 2 Schnell
verbrauch
out SREG,R15
push R0
in R0,SREG
2 Stapel [...] 6
out SREG,R0
pop R0 Kein Register-
Lahm
sts $0060,R0 verbrauch
in R0,SREG
3 SRAM [...] 6
out SREG,R0
lds R0,$0060
Damit ist die Auswahl und Priorität klar. Alles entscheidend ist, ob man Register satt verfügbar hat
oder machen kann.

Oft verwendet man für eine einzelne Flagge gerne das T-Bit im Statusregister. Da gibt es bei allen
drei Methoden einen üblen Fallstrick: Jede Veränderung am T-Bit wird wieder überschrieben, wenn
am Ende der Routine der Originalstatus des Registers wieder hergestellt wird. Bei Methode 1 muss
also Bit 7 des R15 gesetzt werden, damit das T-Bit nach der Beendigung der Routine als gesetzt
resultiert. Obacht: Kann einige Stunden Fehlersuche verursachen!

Verwendung von Registern

Angenommen, eine Interrupt-Service-Routine mache nichts anderes als das Herunterzählen eines
Zählers. Dann ist klar, dass das Register, in dem der Zähler untergebracht ist (z.B. mit .DEF rCnt =
R17 definiert), zu nichts anderem eingesetzt werden kann. Jede andere Verwendung von R17 würde
den Zählrhythmus empfindlich stören.

Dabei hülfe es bei einer Verwendung in der Hauptprogramm-Schleife auch nicht, wenn wir den
Inhalt des Registers mit PUSH rCnt auf dem Stapel ablegen würden und nach seiner Verwendung den
alten Zustand mit POP rCnt wieder herstellen würden. Irgendwann schlägt der Interrupt genau
zwischen dem PUSH und dem POP zu, und dann haben wir den Salat. Das passiert vielleicht nur alle
paar Minuten mal, ein schwer zu diagnostizierender Fehler.

Wir müssten dann schon vor der Ablage auf dem Stapel alle Interrupts mit CLI abschalten und nach
der Verwendung und Wiederherstellung des Registers die Interrupts wieder mit SEI zulassen. Liegen
zwischen Ab- und Anschalten der Interrupts viele Hundert Instruktionen, dann stauen sich die
zwischenzeitlich aufgelaufenen Interrupts und können verhungern. Wenn zwischendurch der Zähler
zwei mal übergelaufen ist, dann geht unsere Uhr danach etwas verkehrt, weil aus den zwei
Ereignissen nur ein Interrupt geworden ist.

Innerhalb einer anderen Interrupt-Service-Routine können wir rCnt auf diese Weise (also mit PUSH
und POP) verwenden, weil diese nicht durch andere Interrupts unterbrochen werden kann. Allerdings
sollte man sich bewusst sein, dass jedes PUSH- und POP-Pärchen vier weitere Taktimpulse
verschwendet. Wer also satt Zeit hat, hat auch Register en masse. Wer keine Register übrig hat,
kommt um so was vielleicht nicht herum.

Manchmal MUSS auf ein Register oder auf einen Teil eines Registers (z.B. ein Bit) sowohl von
innerhalb als auch von außerhalb einer Interrupt-Service-Routine zugegriffen werden, z.B. weil die
ISR dem Hauptprogramm-Loop etwas mitzuteilen hat. In diesen Fällen muss man sich ein klares Bild
vom Ablauf verschaffen. Es muss klar sein, dass Schreibzugriffe sich nicht gegenseitig stören oder
blockieren. Es muss dann auch klar sein, dass dasselbe Register bei zwei nacheinderfolgenden
Lesevorgängen bereits von einem weiteren Interrupt verändert worden sein kann. Liegen die zwei
Zeitpunkte längere Zeit auseinander, dann ist es je nach dem Timing des Gesamtablaufes fast
zwingend, dass irgendwann ein Konflikt auftritt.

An einem Beispiel: sowohl der Timer als auch der ADC haben dem Hauptprogramm etwas
mitzuteilen und setzen jeweils ein Bit eines Flaggenregisters rFlag. Also etwa so:

Isr1:
[...]
sbr rFlag,1<<bitA ; setze Bearbeitungsflagge A
[...]
Isr2:
[...]
sbr rFlag,1<<bitB ; setze Bearbeitungsflagge B
[...]

Wenn jetzt in der Hauptprogrammschleife die beiden Bits


nacheinander abgefragt und Behandlungsroutinen aufgerufen werden,
kann entweder bitA oder bitB oder sowohl bitA als auch bitB gesetzt
sein. Auf jeden Fall müssen die gesetzten Flaggen so schnell wie
möglich wieder auf Null gesetzt werden, denn der nächste Interrupt
kann schon bald wieder zuschlagen. Auf keinen Fall dürfen wir beide
Flaggen erst nach einer aufwändigen Bearbeitung löschen, weil wir
dann vielleicht die nächste Bearbeitungsanforderung verpassen
würden. Es lohnt sich dann, mit der in schnellerer Folge
auftretenden Anforderung zu beginnen und dann die etwas gemütlicher
werkelnde zweite Anforderung zu bearbeiten. Wenn A häufiger ist als
B, z.B. so:

Loop:
sleep ; schlafen legen
nop ; Dummy nach Aufwachen
sbrc rFlag,bitA ; frage erst bitA ab
rcall BearbA ; bearbeite Anforderung A
sbrc rFlag,bitB ; frage dann bitB ab
rcall BearbB ; bearbeite dann Anforderung B
sbrc rFlag,bitA ; frage zur Sicherheit noch mal bitA ab
rcall BearbA ; bearbeite weitere Anforderung A, falls nötig
rjmp Loop ; gehe wieder schlafen
;
BearbA: ; Bearbeite Anforderung A
cbr rFlag,1<<bitA ; lösche vor der Bearbeitung die gesetzte
Flagge
[...]
ret
;
BearbB: ; Bearbeite Anforderung B
cbr rFlag,1<<bitB ; lösche vor der Bearbeitung die gesetzte
Flagge
[...]
ret

Man beachte, dass in beiden Fällen immer nur ein Bit im Register
rFlag zurückgesetzt werden darf, also auf keinen Fall CLR rFlag,
weil es könnten ja in seltenen Fällen auch beide gleichzeitig
gesetzt worden sein.

Ist eine der Behandlungsroutinen ein längliches Monster, z.B. der


Update einer LCD-Anzeige, 16 Schreibvorgänge im EEPROM oder das
Leeren eines Pufferspeichers mit 80 Zeichen im SRAM, dann kann das
zum Verhungern der jeweils anderen Bearbeitungsroutine führen. In
diesen Fällen ist Obacht geboten. Dann muss man eben das EEPROM
auch interrupt-gesteuert befüllen (mit dem EE_RDY-Interrupt), auch
wenn das einigen Programmieraufwand mehr erfordert. Oder sich eine
andere Lösung ausdenken.

Betrachten Sie die genannten Konflikte der Bearbeitung von Signalen


als anspruchsvolle Denksportaufgabe, dann haben Sie den richtigen
Ansatz.

Die oben beschriebene Zugriffssteuerung über eine Interrupt-


Blockage mit CLI/SEI ist auf jeden Fall dann zwingend, wenn ein
Doppelregister außerhalb von Interrupt-Service-Routinen auf einen
neuen Wert gesetzt werden muss und innerhalb von Service-Routinen
verwendet wird. Zwischen dem Setzen des einen Bytes des
Doppelregisters und des zweiten könnte ein Interrupt zuschlagen und
einen völlig verqueren Wert vorfinden. Solche Fehler sind
teuflisch, weil es in der Regel korrekt funktioniert und nur alle
paar Stunden ein Mal dieser Fall eintritt. So einen eingebauten Bug
findet man garantiert nicht, weil er sich so selten in freier
Wildbahn in der Schaltung zeigt.

Daher sollten folgende Regeln gelten:

● Register möglichst klar der alleinigen Verwendung innerhalb und außerhalb von Interrupt-
Service-Routinen zuordnen.
● Jede gemeinsame Nutzung von Registern intensiv auf mögliche Konflikte hin durchdenken.
Vorher denken vermeidet die Fehlersuche hinterher.
● Vorsicht bei der gemeinsamen Nutzung von Doppelregistern. Interrupts blockieren! Und
hinterher nicht vergessen, sie wieder zuzulassen.

To the top of that page

©2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ressourcen.html1/20/2009 7:36:56 PM
http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ablauf_sm.gif

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ablauf_sm.gif1/20/2009 7:36:58 PM
http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ablauf2_sm.gif

http://www.avr-asm-tutorial.net/avr_de/interrupts/int_ablauf2_sm.gif1/20/2009 7:37:01 PM
AVR-Hardware-Testroutinen

Pfad: Home => AVR-Übersicht => Hardware

Tutorial für das Erlernen der


Assemblersprache von
AVR-Einchip-Prozessoren
AT90Sxxxx
von ATMEL anhand geeigneter
praktischer Beispiele.
Hardware auf dem STK board

(Die Links auf die *.asm-Dateien zum Herunterladen mit gedrückter Shift-Taste anklicken.)
HTML- ASM-
Erläuterung zum Inhalt
Format Format
Das EEPROM lesen und beschreiben. Beim Programmieren wird ein im
EEPROM definierter Zähler auf Null gesetzt. Mit jedem Restart wird dieser
um Eins erhöht und sein Inhalt auf den LEDs in Hex ausgegeben. Siehe
EEPROM EEPROM
unbedingt die Hinweise am Ende dieses Programmes, da beim
Programmieren und beim Verifizieren auf dem Board Fehlermeldungen
auftreten werden!
Testet exteres RAM auf dem STK-200 board zählt RAM-Positionen durch
Schreiben von AA und 55 in die einzelnen Positionen, verifiziert den Inhalt
RAM RAM
und gibt bei erfolgreichem Test das MSB der obersten RAM-Adresse auf den
LEDs aus
Löscht das LCD-Display und gibt in Zeile 1 und 2 einen Test-Text aus. Die
nötigen LCD-Grund-Routinen sind sinnigerweise in einer eigenen Include-
LCD LCD
Datei untergebracht, die für alle möglichen Zwecke weiterverwendet werden
kann.
Sendet auf der Schnittstelle mit 9k6 8N1 einen Text und echot dann
SIO SIO eingehende Zeichen zurück. Für die Hardware (Kabel, Stecker, etc.) und das
Terminal- Programm bitte noch diesen Text lesen!
Ähnlich: Sendet die Hexadezimalverschlüsselung der empfangenen Zeichen
SIO SIO
zurück. Die gleichen Hinweise wie oben treffen zu (siehe Text!)

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_hard.html1/20/2009 7:37:06 PM
AVR-Hardware-Tutorium, EEPROM-Test

Pfad: Home => AVR-Übersicht => Hardware => EEPROM

; Demonstriert den Gebrauch des EEPROMs


;
; Beim Programmieren wird ein im EEPROM definierter Zähler
; auf Null gesetzt. Mit jedem Restart wird dieser um Eins
; erhöht und sein Inhalt auf den LEDs in Hex ausgegeben.
; Siehe unbedingt die Hinweise am Ende dieses Programmes!
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Konstanten definieren
;
.equ cnt=$0000 ; Adresse des Zählers im EEPROM
;

; Register definieren
.def mpr=R16 ; Universalregister
.def neu=R17 ; Zählerwert-Zwischenspeicher
;

; Reset-/Interrupt-Vektoren

RJMP main ; Sprung zum Hauptprogramm


;
main:
LDI mpr,$FF ; alle Bits von Port B sind Output
OUT DDRB,mpr

; Programm holt ein Byte aus dem Epromspeicher

LDI mpr,LOW(cnt) ; Übergib die zu lesende Adresse


OUT EEARL,mpr ; im EEPROM an den EEPROM-Port
LDI mpr,HIGH(cnt) ; Low/High-Byte wird separat
OUT EEARH,mpr ; übergeben, da 512 Byte verfügbar
SBI EECR,EERE ; Setze des Read-Enable-Bit EERE im
; EEPROM-Control-Register EECR
IN neu,EEDR ; Lese das Byte aus dem EEPROM-Speicher
; Erhöhe den Zähler und gebe ihn in das EEPROM zurück
INC neu
wart:

; Wenn das EEPROM nicht fertig ist, muss erst gewartet


werden
SBIC EECR,1 ; Frage Bit 1 im EEPROM-Control-Register
RJMP wart ; ab und wiederhole bis EEPROM ready meldet
; Da die EEPROM-Adresse nicht geändert werden muss, entfällt hier
; die Übergabe der EEPROM-Schreibadresse in EEARL/EEARH
OUT EEDR,neu ; Neuen Wert an das EEPROM-Datenregister
; Die beiden Schreibbefehle dürfen nicht unterbrochen werden, da
; die beiden Schreibbefehle sicherheitshalber nach vier Befehlen
; von der Hardware abgebrochen werden. Daher müssen die Interrupts
; (hier nicht eingeschaltet) hier abgeschaltet werden!
CLI

; Jetzt kommen die beiden Schreibbefehle:


SBI EECR,EEMWE ; Schaltet EEPROM Master Write Enable ein
SBI EECR,EEWE ; Löst Schreibvorgang im EEPROM aus
; In den folgenden ca. 1,5 Millisekunden wird das Byte ins EEPROM
; geschrieben. Das stört uns aber nur dann, wenn wieder das EEPROM
; verwendet werden soll. Hier nicht: wir schreiben den invertierten
; Inhalt des Zählers in den Port B an die LEDs und beenden das
; Programm mit einer unendlichen Schleife:
COM neu ; invertieren
OUT PORTB,neu ; an Port B
loop: RJMP loop ; unendlich warten

; Hier beginnt nun das Nullsetzen des EEPROMs beim


Programmieren
; Zuerst wird dem Assembler mitgeteilt, dass der folgende Code in
; das EEPROM gehört:
.ESEG

; Jetzt kommt der EEPROM-Inhalt:


.DB $00 ; Ein Byte mit Null
; Das war es.

; Beim Programmieren muss der Inhalt des EEPROM-Files TESTEEP.EEP


; separat geladen und mitprogrammiert werden! Nicht vergessen!
; Da beim Verifizieren nach dem Programmieren zwischendurch der
; Reset aufgehoben wird und der Prozessor schon einmal durch das
; Programm läuft, geht das Verifizieren des EEPROM-Inhaltes in
; jedem Fall schief. Das gilt auch für jeden Lesezugriff auf das
; EEPROM mit dem Programmiergerät!
; Der Befehl im ISP, den Prozessor neu zu starten, löst ebenfalls
; Mehrfachstarts aus. Durch Aus- und Einschalten vom Board aus kann
; wirklich getestet werden, ob die Zählerei exakt funktioniert.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testeep.html1/20/2009 7:37:08 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testeep.asm

; Demonstriert den Gebrauch des EEPROMs


;
; Beim Programmieren wird ein im EEPROM definierter Zähler
; auf Null gesetzt. Mit jedem Restart wird dieser um Eins
; erhöht und sein Inhalt auf den LEDs in Hex ausgegeben.
; Siehe unbedingt die Hinweise am Ende dieses Programmes!
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Konstanten definieren
;
.equ cnt=$0000 ; Adresse des Zählers im EEPROM
;
; Register definieren
.def mpr=R16 ; Universalregister
.def neu=R17 ; Zählerwert-Zwischenspeicher
;
; Reset-/Interrupt-Vektoren
rjmp main ; Sprung zum Hauptprogramm
;
main:
ldi mpr,$FF ; alle Bits von Port B sind Output
out DDRB,mpr
; Programm holt ein Byte aus dem Epromspeicher
ldi mpr,LOW(cnt) ; Übergib die zu lesende Adresse
out EEARL,mpr ; im EEPROM an den EEPROM-Port
ldi mpr,HIGH(cnt) ; Low/High-Byte wird separat
out EEARH,mpr ; übergeben, da 512 Byte verfügbar
sbi EECR,EERE ; Setze des Read-Enable-Bit EERE im
; EEPROM-Control-Register EECR
in neu,EEDR ; Lese das Byte aus dem EEPROM-Speicher
; Erhöhe den Zähler und gebe ihn in das EEPROM zurück
inc neu
wart:
; Wenn das EEPROM nicht fertig ist, muss erst gewartet werden
sbic EECR,1 ; Frage Bit 1 im EEPROM-Control-Register
rjmp wart ; ab und wiederhole bis EEPROM ready meldet
; Da die EEPROM-Adresse nicht geändert werden muss, entfällt hier
; die Übergabe der EEPROM-Schreibadresse in EEARL/EEARH
out EEDR,neu ; Neuen Wert an das EEPROM-Datenregister
; Die beiden Schreibbefehle dürfen nicht unterbrochen werden, da
; die beiden Schreibbefehle sicherheitshalber nach vier Befehlen
; von der Hardware abgebrochen werden. Daher müssen die Interrupts
; (hier nicht eingeschaltet) hier abgeschaltet werden!
cli
; Jetzt kommen die beiden Schreibbefehle:
sbi EECR,EEMWE ; Schaltet EEPROM Master Write Enable ein
sbi EECR,EEWE ; Löst Schreibvorgang im EEPROM aus
; In den folgenden ca. 1,5 Millisekunden wird das Byte ins EEPROM
; geschrieben. Das stört uns aber nur dann, wenn wieder das EEPROM
; verwendet werden soll. Hier nicht: wir schreiben den invertierten
; Inhalt des Zählers in den Port B an die LEDs und beenden das
; Programm mit einer unendlichen Schleife:
com neu ; invertieren
out PORTB,neu ; an Port B
loop:
rjmp loop ; unendlich warten
; Hier beginnt nun das Nullsetzen des EEPROMs beim Programmieren
; Zuerst wird dem Assembler mitgeteilt, dass der folgende Code in
; das EEPROM gehört:
.ESEG
; Jetzt kommt der EEPROM-Inhalt:
.DB $00 ; Ein Byte mit Null
; Das war es.
; Beim Programmieren muss der Inhalt des EEPROM-Files TESTEEP.EEP
; separat geladen und mitprogrammiert werden! Nicht vergessen!
; Da beim Verifizieren nach dem Programmieren zwischendurch der
; Reset aufgehoben wird und der Prozessor schon einmal durch das
; Programm läuft, geht das Verifizieren des EEPROM-Inhaltes in
; jedem Fall schief. Das gilt auch für jeden Lesezugriff auf das
; EEPROM mit dem Programmiergerät!
; Der Befehl im ISP, den Prozessor neu zu starten, löst ebenfalls
; Mehrfachstarts aus. Durch Aus- und Einschalten vom Board aus kann
; wirklich getestet werden, ob die Zählerei exakt funktioniert.

http://www.avr-asm-tutorial.net/avr_de/quellen/testeep.asm1/20/2009 7:37:09 PM
AVR-Hardware, Externes RAM testen

Pfad: Home => AVR-Übersicht => Hardware => RAM

; ************************************************

; TestRam testet exteres RAM auf dem STK-200


board
; zählt RAM-Positionen durch Schreiben von AA und
; 55 in die einzelnen Positionen, verifiziert den
; Inhalt und gibt bei erfolgreichem Test das MSB
; der obersten RAM-Adresse auf den LEDs aus
; ************************************************

; Erläuterungen zum RAM-Zugriff


; Der MUX-IC 74HC573 und das RAM 62256-70 müssen bestückt sein.
; Port A ist abwechselnd Adress-Bus für das LSB der RAM-Adresse
; und den Datenbus (Multiplex)
; Port C ist der obere Adress-Bus
; Port D Bit 6 ist /RD (Read) am SRAM
; Bit 7 ist /WR (Write) am SRAM
; Die Leitung ALE (Adress Latch Enable) wird verwendet, Pin 30
; Wenn das gesamte externe RAM ok ist, dann müssen die LEDs am
; Ende alle an sein bis auf das achte. Die höchste Adresse
; ist dann bei einem 32k-SRAM 7FFF.

; 8515-Bibliothek laden

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Register
.def mp = R16 ; Multi-Purpose
.def soll = R17 ; enthält abwechselnd AA und 55

; Reset-/Interrupt-Vektor

RJMP main

; Unterprogramme

; Hauptprogramm
main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer
OUT SPL,mp ; wegen verwendeten Unterprogrammen
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Port B steuert die LEDs an

LDI mp,0xFF ; Alles Ausgänge


OUT DDRB,mp ; an Datenrichtungsregister Port B

; Geht wieder nicht complilieren:


; SBI MCUCR,SRE ; Setze das SRAM-Bit im MCU-Register
; Ersatz:
IN mp,MCUCR ; Lese MCU-Control-Register
ORI mp,0x80 ; Setze Bit 7
OUT MCUCR,mp
; Wenn das verwendete SRAM langsamer als 70 ns ist und deshalb
; einen zusätzlichen WAIT-state haben muss, dann muss
; auch das Bit 6 im Port MCUCR gesetzt sein, d.h. der ORI-Befehl
; lautet dann: ORI mp,0xC0 ; Setze Bit 7 und Bit 6

LDI XL,LOW(RAMEND) ; Register XL ist R26, LSB RAM-Adresse


LDI XH,HIGH(RAMEND) ; Register XH ist R27, MSB RAM-Adresse

LDI soll,0b10101010 ; Bitmuster für Test

loop:
INC XL ; Erhöhe Adresszähler um 1
BRNE check ; Nicht Null, MSB ok
INC XH ; Erhöhe MSB der Adresse
BREQ check ; Null, MSB übergelaufen, raus
check:
ST X,soll ; schreibe Bitmuster in SRAM
LD mp,X ; Lese die gleiche SRAM-Adresse
CP mp,soll ; Vergleiche gelesen mit geschrieben
BRNE Zurueck ; Nicht gleich, raus
COM soll ; Drehe alle Bits im Bitmuster um (XOR FF)
ST X,soll ; Noch mal mit 0101.0101
LD mp,X ; Auslesen
CP mp,soll ; Vergleichen
BRNE Zurueck ; Nicht gleich, raus
COM soll ; wieder umdrehen
RJMP loop ; Weitermachen

Zurueck:
LD mp,-X ; Pointer X um eins zurücksetzen, Ergebnis egal
Ungleich:
COM XH ; XOR FF der obersten RAM-Adresse
OUT PORTB,XH ; auf die LEDs
ende: RJMP ende ; Loop für immer

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testram.html1/20/2009 7:37:11 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testram.asm

; ************************************************
; TestRam testet exteres RAM auf dem STK-200 board
; zählt RAM-Positionen durch Schreiben von AA und
; 55 in die einzelnen Positionen, verifiziert den
; Inhalt und gibt bei erfolgreichem Test das MSB
; der obersten RAM-Adresse auf den LEDs aus
; ************************************************
; Erläuterungen zum RAM-Zugriff
; Der MUX-IC 74HC573 und das RAM 62256-70 müssen bestückt sein.
; Port A ist abwechselnd Adress-Bus für das LSB der RAM-Adresse
; und den Datenbus (Multiplex)
; Port C ist der obere Adress-Bus
; Port D Bit 6 ist /RD (Read) am SRAM
; Bit 7 ist /WR (Write) am SRAM
; Die Leitung ALE (Adress Latch Enable) wird verwendet, Pin 30
; Wenn das gesamte externe RAM ok ist, dann müssen die LEDs am
; Ende alle an sein bis auf das achte. Die höchste Adresse
; ist dann bei einem 32k-SRAM 7FFF.
; 8515-Bibliothek laden
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Register
.def mp = R16 ; Multi-Purpose
.def soll = R17 ; enthält abwechselnd AA und 55
; Reset-/Interrupt-Vektor
rjmp main
; Unterprogramme
; Hauptprogramm
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; wegen verwendeten Unterprogrammen
ldi mp,HIGH(RAMEND)
out SPH,mp
; Port B steuert die LEDs an
ldi mp,0xFF ; Alles Ausgänge
out DDRB,mp ; an Datenrichtungsregister Port B
; Geht wieder nicht complilieren:
; SBI MCUCR,SRE ; Setze das SRAM-Bit im MCU-Register
; Ersatz:
in mp,MCUCR ; Lese MCU-Control-Register
ori mp,0x80 ; Setze Bit 7
out MCUCR,mp
; Wenn das verwendete SRAM langsamer als 70 ns ist und deshalb
; einen zusätzlichen WAIT-state haben muss, dann muss
; auch das Bit 6 im Port MCUCR gesetzt sein, d.h. der ORI-Befehl
; lautet dann: ORI mp,0xC0 ; Setze Bit 7 und Bit 6
ldi XL,LOW(RAMEND) ; Register XL ist R26, LSB RAM-Adresse
ldi XH,HIGH(RAMEND) ; Register XH ist R27, MSB RAM-Adresse
ldi soll,0b10101010 ; Bitmuster für Test
loop:
inc XL ; Erhöhe Adresszähler um 1
brne check ; Nicht Null, MSB ok
inc XH ; Erhöhe MSB der Adresse
breq check ; Null, MSB übergelaufen, raus
check:
st X,soll ; schreibe Bitmuster in SRAM
ld mp,X ; Lese die gleiche SRAM-Adresse
cp mp,soll ; Vergleiche gelesen mit geschrieben
brne Zurueck ; Nicht gleich, raus
com soll ; Drehe alle Bits im Bitmuster um (XOR FF)
st X,soll ; Noch mal mit 0101.0101
ld mp,X ; Auslesen
cp mp,soll ; Vergleichen
brne Zurueck ; Nicht gleich, raus
com soll ; wieder umdrehen
rjmp loop ; Weitermachen
Zurueck:
ld mp,-X ; Pointer X um eins zurücksetzen, Ergebnis egal
Ungleich:
com XH ; XOR FF der obersten RAM-Adresse
out PORTB,XH ; auf die LEDs
ende:
rjmp ende ; Loop für immer

http://www.avr-asm-tutorial.net/avr_de/quellen/testram.asm1/20/2009 7:37:13 PM
AVR-Hardware, LCD-Anzeige testen

Pfad: Home => AVR-Übersicht => Hardware => LCD

; ************************************************

; TestLcd löscht das LCD-Display und gibt in


Zeile 1 und 2 einen Test-Text aus.
; ************************************************

; Erläuterungen zum LCD-Zugriff


; Hardware: ; Die LCD-Routinen setzen voraus, dass eine entsprechende
; LCD angeschlossen ist. Das LCD-Board kann mit einer
; Buchsenleiste nach unten hin bestückt werden, so
; dass sie direkt auf das STK200 aufgesetzt werden kann.

;
;Der aufgelötete Connector ...

;
; ... kann direkt auf das Board aufgesteckt werden und ...

;
; ... passt von der Anschlussfolge her schon genau.
; Die 2-Zeilen-LCD-Anzeige muss auf das Board
; aufgesteckt sein, alle erforderliche Hardware ist
; schon auf dem Board vorhanden. Es genügt eine 14-
; polige einreihige Buchsenleiste, die von der Löt-
; seite her auf die LCD aufgelötet und in die 14-
; polige Steckerleiste auf dem STK-200-Board gesteckt
; wird. Das war's an Hardware.
; Ach ja: der Kontrastregler muss noch justiert werden
; sonst ist nichts zu sehen. Also ohne Ansteuerung so
; einstellen, dass die schwarzen Kästchen gerade
; verschwinden.
; Software: Die Ansteuerung erfolgt in diesem Beispiel
; wie Memory (memory-mapped). Das hat den Vorteil,
; dass die gleichen Befehle wie für Memory benutzt
; werden können, das Herumeiern mit den verschiedenen
; Ports entfällt und gleichzeitig SRAM am Board be-
; trieben werden kann. (Die Beispiel-Programme auf
; dem Internet-Server sind alle I/O-mapped und ver-
; tragen sich nicht mit gleichzeitigem Memory-Betrieb!).
; Die Adresse der LCD-Steuerung ist $8000 für die
; Befehle und $C000 für den Zugriff auf den Zeichen-
; generator und die Displayzeilen (jeweils Lesen und
; Schreiben.
; Da bei Memory-Betrieb der Zugriff sehr schnell er-
; folgen würde, muss das WAIT-Bit im MCUCR-Register
; gesetzt werden. Das macht zwar den RAM-Zugriff auch
; langsamer, aber das kann verschmerzt werden. Für
; schnelle RAM-Zugriffe kann das Bit zeitweise wieder
; Null gesetzt werden, dann ist der Nachteil weg.
; Verwendete Ports: Es werden die gleichen Ports verwendet
; wie beim RAM-Zugriff, also:
; Port A ist abwechselnd Adress-Bus für das LSB der RAM-
; Adresse und den Datenbus (Multiplex) des SRAM,
; für die LCD werden diese nicht verwendet, sind
; aber bei Memory-Mapping blockiert!
; Port C ist der obere Adress-Bus beim SRAM, verwendet
; von der LCD werden Bit 7 (Adresse) und 6 (RS-
; Signal an der LCD).
; Port D Bit 6 ist /RD (Read) am SRAM, nicht benutzt von LCD
; Bit 7 ist /WR (Write) am SRAM und an der LCD
;
; Ablauf des Testprogrammes: Nacheinander werden folgende
; Schritte durchlaufen:
; 0. Warten, bis die LCD nicht mehr das BUSY-Flag gesetzt hat
; 1. Löschen des Displays
; 2. Setzen der Übertragungsart (8-Bit), des festen Anzeige-
; fensters und anderer Eigenschaften des Displays
; 3. Ausgabe von zwei Testzeilen mit Text.
; Bei jedem Schritt wird vorher eine Leuchtdiode angemacht,
; so dass bei einem Scheitern an der Nummer der Lampe der
; fehlerhafte Schritt erkannt werden kann. Wenn alles durch-
; laufen wird, sollte die LED 4 an sein und der Text auf der
; LCD zu lesen sein (eventuell Kontrast justieren).
;
; Aufbau der Software: Alle Ansteuerungen der LCD erfolgen
; als Unterprogramme, die leicht in andere Programme über-
; tragen werden können. Verwendete Register sind:
; mp: Allround-Register zur Übergabe von Werten
; R26/R27: XL/XH, 16-Bit-Adresse für den ST X und LD X-Befehl
;
;

; 8515-Bibliothek laden

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Register
.def mp = R16 ; Multi-Purpose
.def test = R17 ; Zählt die einzelnen Testphasen

; Reset-/Interrupt-Vektor

RJMP main

; Unterprogramme zur LCD-Ansteuerung


LcdWt: ; Warte bis das LCD-Busy-Flag gelöscht ist
LDI XH,0x80 ; Oberes Byte der RAM-Adresse der LCD
LDI XL,0x00 ; Unteres Byte der RAM-Adresse der LCD
LD mp,X ; Lese Busy flag und AC-Adresse
ROL mp ; Schiebe Bit 7 in das Carry-Flag
BRCS LcdWt ; Wenn Eins, dann noch busy, weiter
RET

LcdCl: ; Lösche die LCD


LDI mp,0x01 ; Der Löschbefehl für die LCD lautet 01h

LcdBef: ; Gib den Befehl in mp an die LCD, wenn diese bereit ist
PUSH mp ; Der Befehl in mp wird noch gebraucht, auf Stapel
RCALL LcdWt ; Warte, bis Anzeige Befehle entgegen nimmt
POP mp ; Nehme Befehl wieder vom Stapel
ST X,mp ; Gib ihn an die LCD weiter
RET ; Ende des Unterprogrammes

LcdInit: ; Initiiert die Arbeitsweise der LCD


LDI mp,0b00111000 ; 8-Bit-Übertragung, nicht vier Bit
RCALL LcdBef ; an LCD geben
LDI mp,0b00000110 ; Increment, Display freeze
RCALL LcdBef ; an LCD geben
LDI mp,0b00010000 ; Cursor move, nicht shift
RCALL LcdBef ; an LCD geben
RET ; Zurück

LcdBu: ; Schreibe den Buchstaben in mp in die LCD


PUSH mp ; Der Buchstabe wird noch gebraucht, auf Stapel
RCALL LcdWt ; Warte bis die LCD wieder kann
POP mp ; Hole Buchstaben wieder vom Stapel
LDI XH,0xC0 ; Der Speicher der LCD ist auf Adresse 0C00h
ST X,mp ; Schreibe Buchstabe auf LCD
RET ; Zurück aus dem Unterprogramm

LcdTs: ; Schreibe das Wort "Test" in die aktuelle Zeile


PUSH mp ; Rette die Zeilenadresse in mp
RCALL LcdWt ; Warte, bis Display verfügbar ist
POP mp ; Stelle Zeilenadresse wieder her
ORI mp,0x80 ; Setze Bit 7 der Zeilenadresse
RCALL LcdBef ; Gib den Befehl an die LCD weiter
LDI mp,'T' ; Buchstabe T
RCALL LcdBu ; Schreibe Buchstabe in mp auf LCD
LDI mp,'e' ; Buchstabe e
RCALL LcdBu ; Schreibe auf LCD
LDI mp,'s' ; Buchstabe s
RCALL LcdBu ; Schreibe auf LCD
LDI mp,'t' ; Buchstabe t
RCALL LcdBu ; Schreibe auf LCD
RET ; Fertig, Zurück

LcdTst: ; Schreibe das Wort "Test" in Zeile 1 und 2


LDI mp,0x00 ; Zeile 1 beginnt an der Adresse 00h im Display
RCALL LcdTs ; Schreibe Test in Zeile 1
LDI mp,0x40 ; Zeile 2 beginnt an der Adresse 40h im Display
RCALL LcdTs ; Schreibe Test in Zeile 2
RCALL LcdWt ; Warten bis LCD fertig ist
LDI mp,0b00001111 ; Befehl für Display On, Cursor On und Blink
RCALL LcdBef ; Gib Befehl an die Anzeige weiter
RET ; Zurück aus dem Unterprogramm

; Hauptprogramm
main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer
OUT SPL,mp ; wegen verwendeten Unterprogrammen
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Port B steuert die LEDs an

LDI mp,0xFF ; Alles Ausgänge


OUT DDRB,mp ; an Datenrichtungsregister Port B

; Geht wieder nicht complilieren:


; SBI MCUCR,SRE ; Setze das SRAM-Bit im MCU-Register
; Ersatz:
IN mp,MCUCR ; Lese MCU-Control-Register
ORI mp,0xC0 ; Setze Bit 7 (SRAM) und Bit 6 (WAIT-STATE)
OUT MCUCR,mp

; Hier startet der eigentliche Test der LCD


LDI test,0xFE ; Setze Bit 0 auf 0 = Lampe 0 an
OUT PORTB,test ; Lampe 0 an
RCALL LcdWt ; Einfach nur warten,
;falls ein Fehler passiert, bleibt er hier stecken

SEC ; Setze Carry Flag 1


ROL test ; Schiebe die Null eins links, Lampe 1 an
OUT PORTB,test
RCALL LcdCl ; Lösche die LCD

SEC ; Carry wieder an für Lampe 2 an


ROL test ; Und reinschieben in test
OUT PORTB,test
RCALL LcdInit ; Einige Initiierungen der Arbeitsweise

SEC ; Setze Carry Flag 1


ROL test ; Schiebe weiter, Lampe 3 an
OUT PORTB,test
RCALL LcdTst ; Schreibe die beiden Testzeilen

SEC ; Carry wieder 1


ROL test ; Test ist zu Ende, Lampe 4 an
OUT PORTB,test

ende: RJMP ende ; Loop für immer

©2002-2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testlcd.html1/20/2009 7:37:18 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testlcd.asm

; ************************************************
; TestLcd löscht das LCD-Display und gibt in Zeile
; 1 und 2 einen Test-Text aus.
; ************************************************
; Erläuterungen zum LCD-Zugriff
; Hardware: Die 2-Zeilen-LCD-Anzeige muss auf das Board
; aufgesteckt sein, alle erforderliche Hardware ist
; schon auf dem Board vorhanden. Es genügt eine 14-
; polige einreihige Buchsenleiste, die von der Löt-
; seite her auf die LCD aufgelötet und in die 14-
; polige Steckerleiste auf dem STK-200-Board gesteckt
; wird. Das war's an Hardware.
; Software: Die Ansteuerung erfolgt in diesem Beispiel
; wie Memory (memory-mapped). Das hat den Vorteil,
; dass die gleichen Befehle wie für Memory benutzt
; werden können, das Herumeiern mit den verschiedenen
; Ports entfällt und gleichzeitig SRAM am Board be-
; trieben werden kann. (Die Beispiel-Programme auf
; dem Internet-Server sind alle I/O-mapped und ver-
; tragen sich nicht mit gleichzeitigem Memory-Betrieb!).
; Die Adresse der LCD-Steuerung ist $8000 für die
; Befehle und $C000 für den Zugriff auf den Zeichen-
; generator und die Displayzeilen (jeweils Lesen und
; Schreiben.
; Da bei Memory-Betrieb der Zugriff sehr schnell er-
; folgen würde, muss das WAIT-Bit im MCUCR-Register
; gesetzt werden. Das macht zwar den RAM-Zugriff auch
; langsamer, aber das kann verschmerzt werden. Für
; schnelle RAM-Zugriffe kann das Bit zeitweise wieder
; Null gesetzt werden, dann ist der Nachteil weg.
; Verwendete Ports: Es werden die gleichen Ports verwendet
; wie beim RAM-Zugriff, also:
; Port A ist abwechselnd Adress-Bus für das LSB der RAM-
; Adresse und den Datenbus (Multiplex) des SRAM,
; für die LCD werden diese nicht verwendet, sind
; aber bei Memory-Mapping blockiert!
; Port C ist der obere Adress-Bus beim SRAM, verwendet
; von der LCD werden Bit 7 (Adresse) und 6 (RS-
; Signal an der LCD).
; Port D Bit 6 ist /RD (Read) am SRAM, nicht benutzt von LCD
; Bit 7 ist /WR (Write) am SRAM und an der LCD
;
; Ablauf des Testprogrammes: Nacheinander werden folgende
; Schritte durchlaufen:
; 0. Warten, bis die LCD nicht mehr das BUSY-Flag gesetzt hat
; 1. Löschen des Displays
; 2. Setzen der Übertragungsart (8-Bit), des festen Anzeige-
; fensters und anderer Eigenschaften des Displays
; 3. Ausgabe von zwei Testzeilen mit Text.
; Bei jedem Schritt wird vorher eine Leuchtdiode angemacht,
; so dass bei einem Scheitern an der Nummer der Lampe der
; fehlerhafte Schritt erkannt werden kann. Wenn alles durch-
; laufen wird, sollte die LED 4 an sein und der Text auf der
; LCD zu lesen sein (eventuell Kontrast justieren).
;
; Aufbau der Software: Alle Ansteuerungen der LCD erfolgen
; als Unterprogramme, die leicht in andere Programme über-
; tragen werden können. Verwendete Register sind:
; mp: Allround-Register zur Übergabe von Werten
; R26/R27: XL/XH, 16-Bit-Adresse für den ST X und LD X-Befehl
;
;
; 8515-Bibliothek laden
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Register
.def mp = R16 ; Multi-Purpose
.def test = R17 ; Zählt die einzelnen Testphasen
; Reset-/Interrupt-Vektor
rjmp main
; Unterprogramme zur LCD-Ansteuerung
LcdWt:
; Warte bis das LCD-Busy-Flag gelöscht ist
ldi XH,0x80 ; Oberes Byte der RAM-Adresse der LCD
ldi XL,0x00 ; Unteres Byte der RAM-Adresse der LCD
ld mp,X ; Lese Busy flag und AC-Adresse
rol mp ; Schiebe Bit 7 in das Carry-Flag
brcs LcdWt ; Wenn Eins, dann noch busy, weiter
ret
LcdCl:
; Lösche die LCD
ldi mp,0x01 ; Der Löschbefehl für die LCD lautet 01h
LcdBef:
; Gib den Befehl in mp an die LCD, wenn diese bereit ist
push mp ; Der Befehl in mp wird noch gebraucht, auf Stapel
rcall LcdWt ; Warte, bis Anzeige Befehle entgegen nimmt
pop mp ; Nehme Befehl wieder vom Stapel
st X,mp ; Gib ihn an die LCD weiter
ret ; Ende des Unterprogrammes
LcdInit:
; Initiiert die Arbeitsweise der LCD
ldi mp,0b00111000 ; 8-Bit-Übertragung, nicht vier Bit
rcall LcdBef ; an LCD geben
ldi mp,0b00000110 ; Increment, Display freeze
rcall LcdBef ; an LCD geben
ldi mp,0b00010000 ; Cursor move, nicht shift
rcall LcdBef ; an LCD geben
ret ; Zurück
LcdBu:
; Schreibe den Buchstaben in mp in die LCD
push mp ; Der Buchstabe wird noch gebraucht, auf Stapel
rcall LcdWt ; Warte bis die LCD wieder kann
pop mp ; Hole Buchstaben wieder vom Stapel
ldi XH,0xC0 ; Der Speicher der LCD ist auf Adresse 0C00h
st X,mp ; Schreibe Buchstabe auf LCD
ret ; Zurück aus dem Unterprogramm
LcdTs:
; Schreibe das Wort "Test" in die aktuelle Zeile
push mp ; Rette die Zeilenadresse in mp
rcall LcdWt ; Warte, bis Display verfügbar ist
pop mp ; Stelle Zeilenadresse wieder her
ori mp,0x80 ; Setze Bit 7 der Zeilenadresse
rcall LcdBef ; Gib den Befehl an die LCD weiter
ldi mp,'T' ; Buchstabe T
rcall LcdBu ; Schreibe Buchstabe in mp auf LCD
ldi mp,'e' ; Buchstabe e
rcall LcdBu ; Schreibe auf LCD
ldi mp,'s' ; Buchstabe s
rcall LcdBu ; Schreibe auf LCD
ldi mp,'t' ; Buchstabe t
rcall LcdBu ; Schreibe auf LCD
ret ; Fertig, Zurück
LcdTst:
; Schreibe das Wort "Test" in Zeile 1 und 2
ldi mp,0x00 ; Zeile 1 beginnt an der Adresse 00h im Display
rcall LcdTs ; Schreibe Test in Zeile 1
ldi mp,0x40 ; Zeile 2 beginnt an der Adresse 40h im Display
rcall LcdTs ; Schreibe Test in Zeile 2
ldi mp,0b00001111 ; Befehl für Display On, Cursor On und Blink
rcall LcdBef ; Gib Befehl an die Anzeige weiter
ret ; Zurück aus dem Unterprogramm
; Hauptprogramm
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; wegen verwendeten Unterprogrammen
ldi mp,HIGH(RAMEND)
out SPH,mp
; Port B steuert die LEDs an
ldi mp,0xFF ; Alles Ausgänge
out DDRB,mp ; an Datenrichtungsregister Port B
; Geht wieder nicht complilieren:
; SBI MCUCR,SRE ; Setze das SRAM-Bit im MCU-Register
; Ersatz:
in mp,MCUCR ; Lese MCU-Control-Register
ori mp,0xC0 ; Setze Bit 7 (SRAM) und Bit 6 (WAIT-STATE)
out MCUCR,mp
; Hier startet der eigentliche Test der LCD
ldi test,0xFE ; Setze Bit 0 auf 0 = Lampe 0 an
out PORTB,test ; Lampe 0 an
rcall LcdWt ; Einfach nur warten,
;falls ein Fehler passiert, bleibt er hier stecken
sec ; Setze Carry Flag 1
rol test ; Schiebe die Null eins links, Lampe 1 an
out PORTB,test
rcall LcdCl ; Lösche die LCD
sec ; Carry wieder an für Lampe 2 an
rol test ; Und reinschieben in test
out PORTB,test
rcall LcdInit ; Einige Initiierungen der Arbeitsweise
sec ; Setze Carry Flag 1
rol test ; Schiebe weiter, Lampe 3 an
out PORTB,test
rcall LcdTst ; Schreibe die beiden Testzeilen
sec ; Carry wieder 1
rol test ; Test ist zu Ende, Lampe 4 an
out PORTB,test
ende:
rjmp ende ; Loop für immer

http://www.avr-asm-tutorial.net/avr_de/quellen/testlcd.asm1/20/2009 7:37:20 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/lcd_inc.asm

; ********************************************
; * LCD-Interface routines for multi-purpose *
; * use with the ATMEL STK200 board, Version *
; * 0.1 Beta, (C) 1999 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; ********************************************
;
; Purpose:
; Include file for the AVR assembler
; Supplies the common routines to drive an
; LCD connected to the ATMEL STK200 board
; Works best and is compatible to external
; SRAM on that board (up to 32 kB)
;
; Requires:
; mpr ... Multipurpose register, anything
; between R16 and R31, unchanged
; after all routines
; Memory-mapped operation of the LCD
; Setup of the software stack due to the use
; of relative subroutines and PUSH/POP
; LCD properly connected to the board, otherwise
; processor hangs around and waits for
; the busy flag to go down! (no timeout!)
; 39 words of program space
;
; Interfaces:
; lcd_wt Waits indefinately until the busy
; flag of the LCD is off
; lcd_fc Sends the command byte in register
; mpr to the LCD after busy is off
; lcd_cl Clears the LCD and sets cursor to
; the home position, after busy is off
; lcd_st Sets the LCD to 8-bit-transfer,
; freezes the display window and sets
; cursor to increment after busy is off
; lcd_sc Sets cursor to the display position
; in register mpr (Line 1: 00 .. 0F hex,
; Line 2: 40 .. 4F hex)
; lcd_ch Outputs the character in register
; mpr to the LCD after busy is off
; lcd_on Sets display on, cursor on and blink
;
; Adress definitions:
.equ lcd_rs = 0x8000 ; Register select = 0 adress
.equ lcd_ds = 0xC000 ; Register select = 1 adress
;
; Subroutines
;
; Wait until LCD is not busy any more
;
lcd_wt:
push mpr ; save register
lcd_wt1:
lds mpr,lcd_rs ; read busy flag
rol mpr ; Busy = Bit 7 into Carry
brcs lcd_wt1 ; still busy, repeat
pop mpr ; restore register
ret
;
; Outputs the function command in mpr to the LCD
;
lcd_fc:
rcall lcd_wt ; Wait until not busy any more
sts lcd_rs,mpr ; Command byte to LCD
ret
;
; Clears LCD and sets cursor to home position
;
lcd_cl:
push mpr ; save register
ldi mpr,0x01 ; the clear command
rcall lcd_fc ; output to LCD command
pop mpr ; restore register
ret
;
; Sets LCD to 8-bit-mode, display window freeze and
; cursor incrementation (standard mode)
;
lcd_st:
push mpr ; save register
ldi mpr,0b00111000 ; 8-Bit-transfer
rcall lcd_fc ; to LCD command
ldi mpr,0b00000110 ; Increment, display freeze
rcall lcd_fc ; to LCD
ldi mpr,0b00010000 ; Cursor move, not shift
rcall lcd_fc ; to LCD
pop mpr ; restore register
ret
;
; Sets cursor on the LCD to a certain display position in mpr
;
lcd_sc:
push mpr ; save position
ori mpr,0x80 ; set bit 7 of the position
rcall lcd_fc ; position to LCD
pop mpr ; restore register
ret
;
; Sends a character in mpr to the display at the current
; position, position is incremented after write
;
lcd_ch:
rcall lcd_wt ; wait for not busy
sts lcd_ds,mpr ; transfer character to LCD-Display
ret
;
; Sets LCD display on, cursor on and blink on
;
lcd_on:
push mpr ; save register
ldi mpr,0b00001111 ; command byte
rcall lcd_fc ; to LCD
pop mpr ; restore register
ret

http://www.avr-asm-tutorial.net/avr_de/quellen/lcd_inc.asm1/20/2009 7:37:21 PM
AVR-Hardware-Tutorium: SIO ansteuern

Pfad: Home => AVR-Übersicht => Hardware => SIO

; Testet die Serielle Schnittstelle


;
; Sendet auf der Schnittstelle mit 9k6 8N1 einen
; Text und echot dann eingehende Zeichen zurück.
;

; Hardware: Verbindung zwischen Schnittstellen


; Win-Ansteuerung: mit HyperTerminal (siehe Anleitung)
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Konstanten
;
.EQU fq=4000000 ; Quarzfrequenz
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Teiler
;

; Register
;
.DEF mpr=R16 ; Universalregister
.DEF nc=R17 ; Zähler
.DEF c=R18 ; Zeichen
;

;Reset-/Interrupt-Vektoren

RJMP main
;
main: LDI mpr,bdteiler ; Baudgenerator
OUT UBRR,mpr ; Teiler setzen
LDI mpr,0b00011000 ; Enable TX und RX
OUT UCR,mpr ; an UART Control Register
;

; Sende alle Grossbuchstaben


;
LDI c,'A' ; erster Buchstabe
LDI nc,90-65+1 ; Anzahl Buchstaben
tloop: SBIS USR,UDRE ; Springe, wenn Senderegister leer
RJMP tloop ; Warte noch ein Weilchen
OUT UDR,c ; Buchstabe an Senderegister übergeben
INC c ; nächster Buchstabe
DEC nc ; Zähler Anzahl Buchstaben zu senden abwärts
BRNE tloop ; nächster Buchstabe
;

; Warte bis Zeichen empfangen, Echo zurück, für immer


;
rloop: SBIS USR,RXC ; Teste RXC-bit auf vorliegendes Zeichen
RJMP rloop ; Kein Zeichen vorhanden, warte
IN c,UDR ; Hole Zeichen vom UART ab
rwait: SBIS USR,UDRE ; Warte bis Sender bereit
RJMP rwait ; Sender noch nicht frei
OUT UDR,c ; Sende Zeichen aus
CPI c,0x0D ; Return-Zeichen?
BRNE rloop ; Kein Return, einfach weiter
LDI c,0x0A ; Lade Linefeed
RJMP rwait ; Sende noch Linefeed hinterher

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testsio.html1/20/2009 7:37:23 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testsio.asm

; Testet die Serielle Schnittstelle


;
; Sendet auf der Schnittstelle mit 9k6 8N1 einen
; Text und echot dann eingehende Zeichen zurück.
;
; Hardware: Verbindung zwischen Schnittstellen
; Win-Ansteuerung: mit HyperTerminal (siehe Anleitung)
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Konstanten
;
.EQU fq=4000000 ; Quarzfrequenz
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Teiler
;
; Register
;
.DEF mpr=R16 ; Universalregister
.DEF nc=R17 ; Zähler
.DEF c=R18 ; Zeichen
;
;Reset-/Interrupt-Vektoren
rjmp main
;
main:
ldi mpr,bdteiler ; Baudgenerator
out UBRR,mpr ; Teiler setzen
ldi mpr,0b00011000 ; Enable TX und RX
out UCR,mpr ; an UART Control Register
;
; Sende alle Grossbuchstaben
;
ldi c,'A' ; erster Buchstabe
ldi nc,90-65+1 ; Anzahl Buchstaben
tloop:
sbis USR,UDRE ; Springe, wenn Senderegister leer
rjmp tloop ; Warte noch ein Weilchen
out UDR,c ; Buchstabe an Senderegister übergeben
inc c ; nächster Buchstabe
dec nc ; Zähler Anzahl Buchstaben zu senden abwärts
brne tloop ; nächster Buchstabe
;
; Warte bis Zeichen empfangen, Echo zurück, für immer
;
rloop:
sbis USR,RXC ; Teste RXC-bit auf vorliegendes Zeichen
rjmp rloop ; Kein Zeichen vorhanden, warte
in c,UDR ; Hole Zeichen vom UART ab
rwait:
sbis USR,UDRE ; Warte bis Sender bereit
rjmp rwait ; Sender noch nicht frei
out UDR,c ; Sende Zeichen aus
cpi c,0x0D ; Return-Zeichen?
brne rloop ; Kein Return, einfach weiter
ldi c,0x0A ; Lade Linefeed
rjmp rwait ; Sende noch Linefeed hinterher

http://www.avr-asm-tutorial.net/avr_de/quellen/testsio.asm1/20/2009 7:37:24 PM
http://www.avr-asm-tutorial.net/avr_de/TestSio.Txt

Hard- und Software für die Kommunikation mit dem STK-200 über die SIO/UART
==========================================================================

1. Hardware

Benötigt wird ein 9-poliger Stecker für das STK200-Board und entweder eine
25-polige Buchse oder ein weiterer 9-poliger Stecker.
Im neunpoligen Stecker sowie in der 25-poligen Buchse werden jeweils
folgende Pins innerhalb des jeweiligen Steckers miteinander verbunden:

9-polig: 25-polig: Name der Leitung


----------------------------------------------
Pin 4 = Pin 20 = Data Terminal Ready DTR
Pin 8 = Pin 5 = Clear To Send CTS
Pin 6 = Pin 6 = Data Set Ready DSR

Mittels dreiadrigem Kabel werden folgende Leitungen zwischen den beiden


Steckern/Buchsen verbunden:

9-polig: 25-polig: Name der Leitung


----------------------------------------------
Pin 2 = Pin 3 = Read Data RD
Pin 3 = Pin 2 = Transmit Data TD
Pin 5 = Pin 7 = Signal Ground SG

Das war es.

2. Software

Grundsätzlich ist jedes Terminalprogramm geeignet. Am einfachsten unter


Windows ist HyperTerminal, da es bei Win95 dabei ist. Die Installation
der Verbindung geht so:

a) Im Startmenu unter PROGRAMME-ZUBEHÖR-HYPERTERMINAL anklicken.


b) Im offenen Ordner auf HYPERTRM.EXE doppelklicken.
c) Einen Namen für die Verbindung eingeben z.B. STK200Sio und Ok klicken.
d) In dem Rufnummer-Fenster keine Rufnummer eingeben. Das Klappfenster
VERBINDEN_ÜBER aufklappen und DIREKTVERBINDUNG_ÜBER_COMX anwählen.
(X ist in der Regel COM2, wenn die Maus an COM1 hängt.) Ok wählen.
e) Im EIGENSCHAFTEN-Fenster Baudrate 9600 wählen, 8 Datenbits, keine
Parität, 1 Stopbit und Protokoll HARDWARE auswählen.
f) In dem weissen Fenster kann nun beliebig mit dem STK200 kommuniziert
werden. Das Programm sollte beim Einschalten des Boards am Anfang den
Text ausgeben und anschliessend die eingebenen Zeichen per Echo zurück-
senden. Für einen Härtetest z.B. kann man diese Datei senden lassen
(Menuepunkt ÜBERTRAGUNG-TEXTDATEI_SENDEN) und damit die Geschwindig-
keit der Übertragung austesten.
g) Beim Schliessen des Fensters die lästige Frage mit JA beantworten.
Wenn man anschliessend auch die Frage nach dem Speichern der Sitzung
mit JA beantwortet, kann man die gleichen Einstellungen später wieder
verwenden, um schnell Kontakt aufzunehmen. Einfach im HyperTerminal-
Ordner die entsprechende Ikone anklicken.

3. Erfahrungen mit Hyperterminal

Bei Baudraten von 19200 ist Schluss. Darüber geht keine vernünftige Verbin-
dung mehr.

Die Umlaute kommen verkehrt rüber. Das liegt am Windoof.

Am Zeilenanfang geht bei schneller Übertragung immer ein Zeichen verloren,


weil das Carriage-Return beim ECHO im Testprogramm des STK200 um einen
Linefeed ergänzt wird. Dann bleibt nicht genügend Zeit und ein anderer
Buchstabe wird verstümmelt ankommen.

http://www.avr-asm-tutorial.net/avr_de/TestSio.Txt1/20/2009 7:37:26 PM
Empfang und Echo von SIO-Zeichen auf dem STK200 Board

Pfad: Home => AVR-Übersicht => Hardware => SIO-hex

Assembler-Quellcode für das Testen der


Seriellen Schnittstelle
;
; Testet die Serielle Schnittstelle
;
; Empfängt auf der SIO-Schnittstelle mit 9k6 8N1 Zeichen und
; sendet die Hex-Werte dieser Zeichen zurück.
;
; Hardware: Verbindung zwischen Schnittstellen
; Ansteuerung: Terminalprogramm, z.B. HyperTerminal (siehe
Anleitung)
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Konstanten
;
.EQU fq=4000000 ; Quarzfrequenz
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Teiler
.EQU RamStart = 0x0060
;
; Register
;
.DEF mpr=R16 ; Universalregister
.DEF cc=R17 ; Zeichenkopie
.DEF h=R18 ; Hilfsregister
;
; XL/XH = R26/R27 werden als Pointer in das SRAM verwendet
; YL/YH = R28/R29 werden als Pointer in das SRAM verwendet
;
; Programmcode beginnt hier
;
.CSEG
;
; Reset-/Interrupt-Vektoren
;
RJMP main ; Reset-Vektor
;
main:
LDI XH,HIGH(RamStart)
LDI XL,LOW(RamStart)
LDI YH,HIGH(RamStart)
LDI YL,LOW(RamStart)
LDI mpr,0x0D ; Neue Zeile beginnen
ST X+,mpr ; im SRAM ablegen und Pointer erhöhen
LDI mpr,0x0A ; Linefeed dazu
ST X+,mpr
LDI mpr,bdteiler ; Baudgenerator
OUT UBRR,mpr ; Teiler setzen
LDI mpr,0b00011000 ; Enable TX und RX
OUT UCR,mpr ; an UART Control Register
;
; Hauptprogrammschleife fragt SIO-Schnittstelle ab und sendet die
im SRAM
; gespeicherten Zeichen aus
;
tloop:
SBIC USR,RXC ; Springe, wenn das Empfangsregister leer ist
RJMP rx ; Empfange nächstes Zeichen
SBIC USR,UDRE ; Springe, wenn das Senderegister nicht
verfügbar ist
RJMP tx ; Sende nächstes Zeichen
RJMP tloop ; Alles wieder von vorne
;
; Empfange ein Zeichen und speichere es im SRAM
;
rx:
LDI mpr,' ' ; Sende ein Leerzeichen als Trennzeichen
ST X+,mpr ; Speichern im SRAM und Eingabeadresse in X erhöhen
IN mpr,UDR ; Hole Zeichen von der SIO-Schnittstelle ab
MOV cc,mpr ; Lege Kopie an
SWAP mpr ; Oberes und unteres Nibble vertauschen
ANDI mpr,0x0F ; Oberes Nibble löschen
CPI mpr,10 ; Nibble > 9?
BRCS rx1 ; Nein
LDI h,7 ; Addiere 7 für hex A bis F
ADD mpr,h
rx1:
LDI h,'0' ; von 0 nach '0'
ADD mpr,h
ST X+,mpr ; und in das SRAM legen
ANDI cc,0x0F ; Unteres Nibble gleich behandeln
CPI cc,10
BRCS rx2
LDI h,7
ADD cc,h
rx2:
LDI h,'0'
ADD cc,h
ST X+,cc
LDI cc,'h' ; hex-Kennzeichnung mitsenden
ST X+,cc ; auch ins SRAM ablegen
RJMP tloop ; wieder zurück zur Hauptprogrammschleife
;
; Sende Zeichen aus dem SRAM-Puffer, wenn welche dort liegen
;
tx:
CP XL,YL ; Zu sendende Zeichen im Puffer vorhanden?
BREQ tx1 ; Keine Zeichen zu senden
LD mpr,Y+ ; Hole Zeichen aus dem SRAM und erhöhe Y-Pointer
OUT UDR,mpr ; Zeichen an Senderegister übergeben
RJMP tloop ; und wieder zurück in die Hauptprogrammschleife
tx1:
LDI XH,HIGH(RamStart) ; Setze Pointer wieder an den Anfang des
SRAM
LDI XL,LOW(RamStart)
LDI YH,HIGH(RamStart)
LDI YL,LOW(RamStart)
RJMP tloop ; und zurück in die Hauptprogrammschleife
;
; Code Ende
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/siohex.html1/20/2009 7:37:28 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/siohex.asm

;
; Testet die Serielle Schnittstelle
;
; Empfängt auf der SIO-Schnittstelle mit 9k6 8N1 Zeichen und
; sendet die Hex-Werte dieser Zeichen zurück.
;
; Hardware: Verbindung zwischen Schnittstellen
; Ansteuerung: Terminalprogramm, z.B. HyperTerminal (siehe Anleitung)
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Konstanten
;
.EQU fq=4000000 ; Quarzfrequenz
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Teiler
.EQU RamStart = 0x0060
;
; Register
;
.DEF mpr=R16 ; Universalregister
.DEF cc=R17 ; Zeichenkopie
.DEF h=R18 ; Hilfsregister
;
; XL/XH = R26/R27 werden als Pointer in das SRAM verwendet
; YL/YH = R28/R29 werden als Pointer in das SRAM verwendet
;
; Programmcode beginnt hier
;
.CSEG
;
; Reset-/Interrupt-Vektoren
;
rjmp main ; Reset-Vektor
;
main:
ldi XH,HIGH(RamStart)
ldi XL,LOW(RamStart)
ldi YH,HIGH(RamStart)
ldi YL,LOW(RamStart)
ldi mpr,0x0D ; Neue Zeile beginnen
st X+,mpr ; im SRAM ablegen und Pointer erhöhen
ldi mpr,0x0A ; Linefeed dazu
st X+,mpr
ldi mpr,bdteiler ; Baudgenerator
out UBRR,mpr ; Teiler setzen
ldi mpr,0b00011000 ; Enable TX und RX
out UCR,mpr ; an UART Control Register
;
; Hauptprogrammschleife fragt SIO-Schnittstelle ab und sendet die im SRAM
; gespeicherten Zeichen aus
;
tloop:
sbic USR,RXC ; Springe, wenn das Empfangsregister leer ist
rjmp rx ; Empfange nächstes Zeichen
sbic USR,UDRE ; Springe, wenn das Senderegister nicht verfügbar ist
rjmp tx ; Sende nächstes Zeichen
rjmp tloop ; Alles wieder von vorne
;
; Empfange ein Zeichen und speichere es im SRAM
;
rx:
ldi mpr,' ' ; Sende ein Leerzeichen als Trennzeichen
st X+,mpr ; Speichern im SRAM und Eingabeadresse in X erhöhen
in mpr,UDR ; Hole Zeichen von der SIO-Schnittstelle ab
mov cc,mpr ; Lege Kopie an
swap mpr ; Oberes und unteres Nibble vertauschen
andi mpr,0x0F ; Oberes Nibble löschen
cpi mpr,10 ; Nibble > 9?
brcs rx1 ; Nein
ldi h,7 ; Addiere 7 für hex A bis F
add mpr,h
rx1:
ldi h,'0' ; von 0 nach '0'
add mpr,h
st X+,mpr ; und in das SRAM legen
andi cc,0x0F ; Unteres Nibble gleich behandeln
cpi cc,10
brcs rx2
ldi h,7
add cc,h
rx2:
ldi h,'0'
add cc,h
st X+,cc
ldi cc,'h' ; hex-Kennzeichnung mitsenden
st X+,cc ; auch ins SRAM ablegen
rjmp tloop ; wieder zurück zur Hauptprogrammschleife
;
; Sende Zeichen aus dem SRAM-Puffer, wenn welche dort liegen
;
tx:
cp XL,YL ; Zu sendende Zeichen im Puffer vorhanden?
breq tx1 ; Keine Zeichen zu senden
ld mpr,Y+ ; Hole Zeichen aus dem SRAM und erhöhe Y-Pointer
out UDR,mpr ; Zeichen an Senderegister übergeben
rjmp tloop ; und wieder zurück in die Hauptprogrammschleife
tx1:
ldi XH,HIGH(RamStart) ; Setze Pointer wieder an den Anfang des SRAM
ldi XL,LOW(RamStart)
ldi YH,HIGH(RamStart)
ldi YL,LOW(RamStart)
rjmp tloop ; und zurück in die Hauptprogrammschleife
;
; Code Ende
;

http://www.avr-asm-tutorial.net/avr_de/quellen/siohex.asm1/20/2009 7:37:29 PM
AVR-Tutorial, Voraussetzungen

Pfad: Home => AVR-Übersicht => Tutorial

Tutorial für das Erlernen der


Assemblersprache von
AVR-Einchip-Prozessoren
AT90Sxxxx
von ATMEL anhand geeigneter
praktischer Beispiele.
Sinn, Zweck und
Voraussetzungen

Sinn und Zweck


Die folgenden Lektionen führen in die Programmierung von AVR-Einchip-Prozessoren der Serien
AT90Sxxxx der Firma ATMEL ein. Nach Durcharbeiten der Beispiele sollte jeder auch ohne
Vorkenntnisse in der Lage sein, einfache Programme für diese Prozessoren zu erstellen. Die Beispiele
können direkt im Assembler kompiliert, in den Chip übertragen werden und gestartet werden. Jeder
Programmierschritt ist ausführlich kommentiert.

Voraussetzungen
Alle Beispiele sind auf den ATMEL-Assembler ausgelegt. Bei Verwendung anderer Assembler
müssen eventuell Anpassungen an einzelnen Befehlen in Bezug auf die Syntax vorgenommen werden.
Die Beispiele laufen direkt auf dem STK-200-Programmierboard, das von der Firma ATMEL
vertrieben wird und im Versandhandel zu beschaffen ist. Für alle Hardware-Komponenten auf diesem
Board werden Beispiele zu deren Programmierung und Ansteuerung angegeben.
ACHTUNG! Alle Beispiele setzen voraus, dass sich die Datei "8515def.inc" im gleichen Verzeichnis
wie der Quellcode befindet, sonst hagelt es Fehlermeldungen vom Assembler. Die Datei findet sich
bei installiertem Assembler im Verzeichnis X:\avrtools\appnotes\ und kann von dort in das
Quellcode- Verzeichnis kopiert werden.

Vorgehen
Bei blutigen Anfängern: Die Beispiele nacheinander in den Editor laden und die kommentierten
Befehle lesen, die einzelnen Programmschritte verstehen, den Quelltext assemblieren und auf dem
Board laufen lassen.
Fortgeschrittene: Den entsprechenden Quelltext für die Komponente heraussuchen und die
komponentenspezifischen Befehle verstehen, eventuell für eigene Zwecke anpassen.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_allg.html1/20/2009 7:37:33 PM
Quellcode LCD-Include-Routine

Pfad: Home => AVR-Übersicht

Assembler-Quellcode der LCD-Include-


Routinen für das STK200
; ***********************************************
; * LCD-Interface routines for multi-purpose *
; * use with the ATMEL STK200 board, Version *
; * 0.1 Beta, (C) 1999 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; ***********************************************
;
; Purpose:
; Include file for the AVR assembler
; Supplies the common routines to drive an
; LCD connected to the ATMEL STK200 board
; Works best and is compatible to external
; SRAM on that board (up to 32 kB)
;
; Requires:
; mpr ... Multipurpose register, anything
; between R16 and R31, unchanged
; after all routines
; Memory-mapped operation of the LCD
; Setup of the software stack due to the use
; of relative subroutines and PUSH/POP
; LCD properly connected to the board, otherwise
; processor hangs around and waits for
; the busy flag to go down! (no timeout!)
; 39 words of program space
;
; Interfaces:
; lcd_wt Waits indefinately until the busy
; flag of the LCD is off
; lcd_fc Sends the command byte in register
; mpr to the LCD after busy is off
; lcd_cl Clears the LCD and sets cursor to
; the home position, after busy is off
; lcd_st Sets the LCD to 8-bit-transfer,
; freezes the display window and sets
; cursor to increment after busy is off
; lcd_sc Sets cursor to the display position
; in register mpr (Line 1: 00 .. 0F hex,
; Line 2: 40 .. 4F hex)
; lcd_ch Outputs the character in register
; mpr to the LCD after busy is off
; lcd_on Sets display on, cursor on and blink
;
; Adress definitions:
.equ lcd_rs = 0x8000 ; Register select = 0 adress
.equ lcd_ds = 0xC000 ; Register select = 1 adress
;
; Subroutines
;
; Wait until LCD is not busy any more
;
lcd_wt: PUSH mpr ; save register
lcd_wt1:
LDS mpr,lcd_rs ; read busy flag
ROL mpr ; Busy = Bit 7 into Carry
BRCS lcd_wt1 ; still busy, repeat
POP mpr ; restore register
RET
;
; Outputs the function command in mpr to the LCD
;
lcd_fc: RCALL lcd_wt ; Wait until not busy any more
STS lcd_rs,mpr ; Command byte to LCD
RET
;
; Clears LCD and sets cursor to home position
;
lcd_cl: PUSH mpr ; save register
LDI mpr,0x01 ; the clear command
RCALL lcd_fc ; output to LCD command
POP mpr ; restore register
RET
;
; Sets LCD to 8-bit-mode, display window freeze and
; cursor incrementation (standard mode)
;
lcd_st: PUSH mpr ; save register
LDI mpr,0b00111000 ; 8-Bit-transfer
RCALL lcd_fc ; to LCD command
LDI mpr,0b00000110 ; Increment, display freeze
RCALL lcd_fc ; to LCD
LDI mpr,0b00010000 ; Cursor move, not shift
RCALL lcd_fc ; to LCD
POP mpr ; restore register
RET
;
; Sets cursor on the LCD to a certain display position in mpr
;
lcd_sc: PUSH mpr ; save position
ORI mpr,0x80 ; set bit 7 of the position
RCALL lcd_fc ; position to LCD
POP mpr ; restore register
RET
;
; Sends a character in mpr to the display at the current
; position, position is incremented after write
;
lcd_ch: RCALL lcd_wt ; wait for not busy
STS lcd_ds,mpr ; transfer character to LCD-Display
RET
;
; Sets LCD display on, cursor on and blink on
;
lcd_on: PUSH mpr ; save register
LDI mpr,0b00001111 ; command byte
RCALL lcd_fc ; to LCD
POP mpr ; restore register
RET
©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/lcd_inc.html1/20/2009 7:37:34 PM
Include routine for LCD displays on the ATMEL STK200 board

Pfad: Home => AVR-Übersicht

Assembler-Quellcode der LCD-Include-


Demonstration für das STK200
; *****************************************************
; * Demonstrates the use of the Include routines *
; * LCD_INC.ASM for use with the LCD on board of the *
; * ATMEL STK200 (C) 1999 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; *****************************************************
;

.NOLIST
.INCLUDE "8515def.inc"
.LIST

.def mpr=R16 ; My multipurpose register, required

; Reset-/Interrupt-Vectors

RJMP main

; Includes the LCD-routines, file must be in the same path

.INCLUDE "LCD_INC.ASM"

; Main program

main: LDI mpr,LOW(RAMEND) ; Set up stack


OUT SPL,mpr
LDI mpr,HIGH(RAMEND)
OUT SPH,mpr
LDI mpr,0xC0 ; Switch on external SRAM and WAIT
OUT MCUCR,mpr
RCALL lcd_cl ; Clears display
RCALL lcd_st ; Standard display mode
LDI mpr,0x05; Cursor position to line 1, col 5
RCALL lcd_sc
LDI mpr,'H' ; Output Hello World
RCALL lcd_ch
LDI mpr,'e'
RCALL lcd_ch
LDI mpr,'l'
RCALL lcd_ch
RCALL lcd_ch
LDI mpr,'o'
RCALL lcd_ch
LDI mpr,0x45 ; Cursor position to line 2, col 5
RCALL lcd_sc
LDI mpr,'W'
RCALL lcd_ch
LDI mpr,'o'
RCALL lcd_ch
LDI mpr,'r'
RCALL lcd_ch
LDI mpr,'d'
RCALL lcd_ch
LDI mpr,'!'
RCALL lcd_ch
RCALL lcd_on
loop: RJMP loop ; Uff! Next week we learn how to create and read a table
©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/lcd_test.html1/20/2009 7:37:36 PM
AVR-Tutorial

Pfad: Home => AVR-Übersicht => SIO-Spezial

Tutorial für das Erlernen der


Assemblersprache von
AVR-Einchip-Prozessoren AT90Sxxxx
von ATMEL anhand geeigneter
praktischer Beispiele.
STK board über die SIO an
PC anschliessen

Anmerkung: Die Dateien testsint.asm, sioint.asm und bcdmath.asm enthielten einen ernsten Fehler
(dauerhafte Interrupts der SIO). Da die Routine sioint.asm externes SRAM erforderlich macht und
daher am STK500 ohnehin nicht funktioniert, wurde dieser Quellcode vorläufig aus dem
Quellenverzeichnis genommen.

Sorry, manche Fehler merkt man erst nach vielen Monaten.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_sio.html1/20/2009 7:37:39 PM
<A HREF="beginner/werkzeuge.html#assembler">Assembler</A> Quellcode des AVR Keyboard-Tests

Pfad: Home => AVR-Übersicht => Hardware => Keyboard-Benutzung

Test eines Keyboards an Port B


; Test des Keyboards
;
; Liest das Keyboard am Port B und zeigt die gedrückte Taste auf den LEDs
; in hexadezimaler Form aus.
;
; Keyboard ist an Port B angeschlossen:
; Bit 6: *=Bit0 7=Bit1 4=Bit2 1=Bit3
; Bit 5: 0=Bit0 8=Bit1 5=Bit2 2=Bit3
; Bit 4: #=Bit0 9=Bit1 6=Bit2 3=Bit3
;
; 8515-Definitionen
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Register
.def mpko=R15 ; Alter Tastenstand
.def mpr=R16 ; Multifunktionsregister
.def mpk=R25 ; Multifunktionsregister für Keyboard-Interrupt
;
; RAM-Adressen
.equ taste=$0060 ; Erste Ramadresse, Hier kommt die Taste hin
;
; Reset-/Interruptvektoren
RJMP main
RETI ; Ext Int 0
RETI ; Ext Int 1
RETI ; TC1 Capture
RJMP test ; TC1 Compare A
RETI ; Compare B
RETI ; TC1 Overflow
RETI ; TC0 Overflow
RETI ; Serial Transfer Complete
RETI ; Serial Rx Complete
RETI ; Data Register Empty
RETI ; Serial Tx Complete
RETI ; Analog Comparator

; Hauptprogramm
main:
LDI mpr,HIGH(RAMEND) ; Stack Pointer Init wegen Interrupts
OUT SPH,mpr
LDI mpr,LOW(RAMEND)
OUT SPL,mpr

; General control register


CLR mpr ; kein SRAM, kein Wait, kein Sleep-Mode,
OUT MCUCR,mpr ; Ext.Int egal

; Port B ist Output und Tastatur-Input


LDI mpr,0x70 ; alles auf Output
OUT DDRB,mpr
LDI mpr,0x00 ; alle Lampen an
OUT PORTB,mpr
STS Taste,mpr
;
; Timer/Counter 0 initiieren
LDI mpr,$00 ; Prescaler = 256
OUT TCCR0,mpr

; Timer 1 initiieren
LDI mpr,0b00000000 ; Disable Timer Output und PWM-Mode
OUT TCCR1A,mpr ; in Timer Control Register 1A
LDI mpr,0b00001011 ; No input noise canceling, clear counter after
; match, Prescaler = 64 ==> 62500 Hz = 16 µs
OUT TCCR1B,mpr ; in Timer Control Register 1B
LDI mpr,HIGH(625) ; Compare-Wert in Compare-Register A
OUT OCR1AH,mpr ; High Byte zuerst
LDI mpr,LOW(625)
OUT OCR1AL,mpr ; Low Byte zuletzt
LDI mpr,0xFF ; No Interrupt on Compare B
OUT OCR1BH,mpr ; High Byte zuerst
OUT OCR1BL,mpr ; Low Byte zuletzt

; Interrupts starten
CLR mpr ; External interrupts disable
OUT GIMSK,mpr ; an General Interrupt mask register
LDI mpr,0b01000000 ; Timer 1: Overflow Int Off, Compare A Int on,
OUT TIMSK,mpr ; Compare B Int Off, Input Int Off, Timer 0: Int Off
SEI ; Interrupts zulassen

; Unendlicher Loop, alles Interrupt-gesteuert


loop: RJMP loop

; Interrupt Rountine bei TC1 Compare Match B


tc1ci: IN mpk,SREG ; Status-Register retten
PUSH mpk
LDI mpk,0b11110000 ; Oberes Nibble Ausgabe, Unteres Eingabe
OUT DDRB,mpk ; an Port B
LDI mpk,0x0F ; Oberes Nibble gibt Null aus, unteres setzt Pullups
OUT PORTB,mpk
IN mpk,PINB ; Lese Ergebnis von Tastatur
CP mpk,mpko ; Vergleiche mit altem Stand
BREQ tc1cir ; Keine Änderung, Rückkehr
MOV mpko,mpk ; Kopiere neuen Stand in alten Stand
STS taste,mpk ; Neuer LED-Stand
tc1cir: LDI mpk,0xFF ; Port B wieder auf Ausgabe
OUT DDRB,mpr
LDS mpk,taste ; gedrückte Taste auf LEDs ausgeben
OUT PORTB,mpk
POP mpk ; Rückkehr vom Interrupt
OUT SREG,mpk ; Status-Register wieder herstellen
RETI

tc0ci: LDI mpr,0xFF


OUT PORTB,mpr
RETI
tc2ci: LDI mpr,0xAA
OUT PORTB,mpr
RETI
test:
; LDI mpk,0x0F
; OUT DDRB,mpk
; LDI mpk,0xF0
; OUT PORTB,mpk
RETI

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testkbd.html1/20/2009 7:37:41 PM
AVR-Anwendungen

Pfad: Home => AVR-Übersicht => Anwendungen

AVR-Einchip-Prozessoren
AT90Sxxxx
von ATMEL in praktischen Beispielen.

Die folgenden Beispiele sind kleine Anwendungen zum Ausprobieren und für ernsthafte
Anwendungen. Sie wurden zwar erprobt und angewendet, eine Garantie für ihr korrektes
Funktionieren kann aber verständlicherweise nicht übernommen werden.
HTML- ASM-
Kurzbeschreibung Link
Format Format
DCF77-synchronisierbare Digitaluhr mit seriellem
Interface zur Steuerung und Diagnose mit einem
Terminalprogramm mit ANSI-Darstellung. Arbeitet mit GIF
DCF77Uhr DCF77Uhr einem 10MHz-AT90S2313 in einer speziellen Schaltung
PDF
(Schaltplan siehe unter Links). (Quelltext bisher nur in
englischer Version verfügbar! 1211 Zeilen, übersetze ich
nur auf mehrfache Anfragen.)
PCM-kodierte Fernsteuersignale von 0,8 bis 2,2 ms
werden mittels eines AT90S2323 in einer sehr kleinen
PcmDec PcmDec PcmDec
Schaltung in einen Analogwert von 0 bis 5 Volt
umgewandelt.
Rechteckgenerator, erzeugt beliebig lange, exakte Signale
und ist über den SIO-Eingang des STK200 boards mit
PwgSio PwgSio PwgSio
einem Terminalprogramm mit ANSI-Darstellung frei
einstellbar und bedienbar.
Rechteckgenerator mit einstellbarer Frequenz und
Hauptprogramm, Pulsweite, normalem und invertiertem Digitalausgang,
Gezippte
LCD-Routinen, Frequenz/Zeit/UPM/Pulsweite-Anzeige auf LCD, RectGen
Quellen
Frequenztabelle Anwendung eines ATmega8 mit ADC, Quarzoszillator,
etc.
Frequenzzähler, misst Frequenzen bis zu 40 MHz und
fcount_m8_v3 fcountV2 zeigt Frequenz, Umdrehungszahl, Periodendauer, fcount
Periodenanteile und eine Spannung an, mit SIO-Interface
ATtiny2313-Eieruhr zum Angeben, Vielzweck-Geschenk
eieruhr eieruhr in Dutzenden Varianten zum individuellen Beschenken Eieruhr
des gesamten Bekanntenkreises
ATtiny13-Schrittmotorsteuerung, Einstellung eines
schrittmotor schrittmotor Schrittmotors mit einer Analogspannung von 0..5V, Stepper
einstellbar bis 65535 Einzelschritte Vollausschlag

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/apps.html1/20/2009 7:37:44 PM
DCF77 Uhr mit dem AVR-Controller AT90S2313

Pfad: Home => AVR-Übersicht => Anwendungen => DCF77 Uhr

; ***************************************************************
; * DCF-synchronized Digital Clock for RS232 communication on *
; * a 2313-Experimental-Board, Version 0.2 as of 12.01.2001 *
; * Features: XTal driven digital clock for exact date and time *
; * information, adjusted and read over a SIO-I/O 9k6 8N1 *
; * connection, Self-adjusting date- and time-synchronisation *
; * to a connected receiver for the Frankfurt/Germany based *
; * official clock reference DCF77 (optional) *
; * (C)2001 by Gerhard Schmidt *
; * report bugs to info!at!avr-asm-tutorial.net *
; ***************************************************************
;
; Hardware requirements:
; - 2313 board (see extra doc)
; - RS232 compatible terminal, e.g. PC+Win+HyperTerminal to
adjust/read
; the date and time informationen
; - (RXD/TXD, RTS/CTS)-crosswired RS232 cable connection between
the
; 2313-board and the terminal
; - Optional: DCF77 clock with active low receiver signal (second
ticks)
;
; Software features:
; - Interrupt-driven and buffered SIO-I/O with RTS/CTS hardware
protocol
; - Interrupt-driven clock signals with exact timing
; - SLEEP mode for reduced power consumption of the MPU
; - Exact date calculation from 2001 up to the year 2099
; - Transmits ANSI color codes for terminal control
; - DCF synchronisation: self-adjusting to unexact signal
lengthes and
; spurious signals by software, loss-of-signal-detection, full
parity bit
; checking, convenient hardware debugging opportunities by
terminal display
; of the signal length and all detected errors during the
sampling process
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2313def.inc"
.LIST
;
; Constants
;
; Constants for Sio properties
.EQU fq=10000000; Xtal frequency on board in Hz
.EQU baud=9600; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.EQU ticks=fq/16000; ticks per second for the timing functions
; Constants for Sio communications
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cBs=0x08; Backspace character
; Bit assignment of the RTS and CTS pins on Port B
.EQU bIRts = 2
.EQU bOCts = 4
; Locations in the Internal SRAM
.EQU sDTF = 0x60 ; Date/Time information, first location in SRAM
.EQU dDDT = 0 ; relative distance, Tens of Days
.EQU dDD = 1 ; relative distance, Days
.EQU dDMT = 3 ; relative distance, Tens of Monthes
.EQU dDM = 4 ; relative distance, Month
.EQU dDY = 9 ; relative distance, Years
.EQU dTHT = 12 ; relative disance, Tens of Hours
.EQU dTH = 13 ; relative distance, Hours
.EQU dTMT = 15 ; relative distance, Tens of Minutes
.EQU dTM = 16 ; relative distance, Minutes
.EQU dTST = 18 ; relative distance, Tens of Seconds
.EQU dTS = 19 ; relative distance, Seconds
.EQU sDTL = 0x74 ; Date/Time information, last location in SRAM
.EQU sDTT = 0x6C ; Position of Time
.EQU sSec = 0x73 ; Adress of seconds
.EQU sSecT = 0x72 ; Adress of tens of seconds
.EQU sMin = 0x70 ; Adress of minutes
; Constants for Sio Rx- and Tx-Buffers
.EQU RxBuF = 0x75 ; Sio Rx-Buffer, first location in SRAM
.EQU RxBuL = 0x84 ; Sio Rx-Buffer, last location in SRAM (16
Bytes)
.EQU TxBuF = 0x85 ; Sio Tx-Buffer, first location in SRAM
.EQU TxBuL = 0xA4 ; Sio Tx-Buffer, last location in SRAM (32
Bytes)
;
; Used registers
;
; Register mainly for Program Memory Read Operations
.DEF rlpm = R0 ; Used for read operations with LPM
; SIO Tx Buffer In pointer
.DEF rsiotxin = R1
; Registers for the DCF77-Receiver option
.DEF rdcfp = R2 ; Parity bit counter for DCF signals
.DEF rdcf1 = R3 ; Last Receiver Shift Register
.DEF rdcf2 = R4 ; Receiver Shift register
.DEF rdcf3 = R5 ; Receiver Shift register
.DEF rdcf4 = R6 ; Receiver Shift register
.DEF rdcf5 = R7 ; First Receiver Shift Register
.DEF rDcfCmp = R8 ; Compare length of DCF pulse (self-adjusted)
.DEF rDcfLc = R9 ; Last count length detected
.EQU cDcfCmpDflt = 125 ; Default length for DCF signals (self-
adjusted)
.DEF rDcfCnt = R10 ; DCF length count, interrupt driven
.DEF rDcfL0 = R11 ; Distance of last short pulse from medium
count length
.DEF rDcfL1 = R12 ; Distance of last long pulse from medium count
length
; For all purposes
.DEF rmpr = R16 ; Multi-purpose register
; Low level ticker for seconds counting by interrupt (1.6 ms)
.DEF rtckh = R17 ; MSB
.DEF rtckl = R18 ; LSB
; DCF77 Tick register for signal length, driven by timer interrupt
(1.6 ms)
.DEF rDcfl = R19
; Timer 0 flag register with the following bits:
.DEF rdtf = R20 ; Date/Time Flag register
.EQU bEos = 0 ; Bit 0: End of second reached
.EQU mEos = 1
.EQU bMin = 1 ; Bit 1: Echo minutes only
.EQU mMin = 2
.EQU bDTm = 2 ; Bit 2: DT mode active
.EQU mDTm = 4
; Bits used by DCF77:
.EQU bDcfm = 3 ; Bit 3: DCF mode active
.EQU mDcfm = 8
.EQU bDcfCtm = 4 ; Bit 4: DCF echo counters
.EQU mDcfCtm = 16
.EQU bDcfSync = 5 ; Bit 5: DCF synch tickers at next second
.EQU mDcfSync = 32
.EQU bDcfRdy = 6 ; Bit 6: DCF bit ready
.EQU mDcfRdy = 64
.EQU bDcfOk = 7 ; Bit 7: DCF Signal is ok
.EQU mDcfOk = 128
; SIO flag register
; Bit 5: Unused
; Bit 6: Unused
; Bit 7: Unused
.DEF rsioflg = R21 ; SIO flag register
.EQU bEcho = 0 ; Bit 0: Echo all incoming characters
.EQU mEcho = 1
.EQU bAddLf = 1 ; Bit 1: Insert LF after CR
.EQU mAddLf = 2
.EQU bTxBAct = 2 ; Bit 2: Transmitter buffer active
.EQU mTxBAct = 4
.EQU bTxAct = 3 ; Bit 3: Character transmission active
.EQU mTxAct = 8
.EQU bRxCmp = 4 ; Bit 4: Rx-Line complete
.EQU mRxCmp = 16
; DCF error flag register
.DEF rDcfErr = R22 ; Last DCF-error
.EQU bDcfPem = 0 ; Bit 0: Parity error minute
.EQU mDcfPem = 1
.EQU bDcfPeh = 1 ; Bit 1: Parity error hour
.EQU mDcfPeh = 2
.EQU bDcfPed = 2 ; Bit 2: Parity error date
.EQU mDcfPed = 4
.EQU bDcfCts = 3 ; Bit 3: Count too short
.EQU mDcfCts = 8
.EQU bDcfCtl = 4 ; Bit 4: Count too long
.EQU mDcfCtl = 16
.EQU bDcfSok = 5 ; Bit 5: Synchronisation ( not an error!)
.EQU mDcfSOk = 32
.EQU bDcfEtr = 6 ; Bit 6: Error to be reported
.EQU mDcfEtr = 64
.EQU bDcfAny = 7 ; Bit 7: Any error
.EQU mDcfAny = 128
; DCF shift register counter
.DEF rDcfs = R23 ; Shift Register Bit Counter
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-vectors
;
RJMP Start ; Reset-vector
RJMP IInt0 ; External Interrupt Request 0
RJMP IInt1 ; External Interrupt Request 1
RJMP TCpt1 ; Timer/Counter1 Capture event
RJMP TCmp1 ; Timer/Counter1 Compare match
RJMP TOvf1 ; Timer/Counter1 Overflow
RJMP TOvf0 ; Timer/Counter0 Overflow
RJMP URxAv ; Uart Rx char available
RJMP UTxDe ; Uart Tx data register empty
RJMP UTxCp ; Uart Tx complete
RJMP AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0: Started by a negative edge on the DCF input
;
IInt0:
PUSH rmpr
IN rmpr,SREG
SBRS rdtf,bDcfSync
RJMP IInt01
CBR rdtf,mDcfSync ; Synchronize DCF and internal tickers
CLR rtckl
CLR rtckh
IInt01:
CLR rDcfl
OUT SREG,rmpr
POP rmpr
RETI
;
; External Interrupt 1 : Started by a positive edge on the DCF input
;
IInt1:
PUSH rmpr
IN rmpr,SREG
CPI rDcfl,10 ; Exclude short signals
BRCS IInt1r
MOV rDcfCnt,rDcfl ; Store count length
INC rDcfs
SBR rdtf,mDcfRdy ; Flag received bit ready
IInt1r:
OUT SREG,rmpr
POP rmpr
RETI
;
; Timer/Counter 1, Capture event interrupt, not used
;
TCpt1:
RETI
;
; Timer/Counter 1, Compare match interrupt, not used
;
TCmp1:
RETI
;
; Timer/Counter 1, Overflow interrupt, not used
;
TOvf1:
RETI
;
; Timer/Counter 0, Overflow interrupt, used to count times
;
TOvf0:
PUSH rmpr ; Save Register rmpr
LDI rmpr,6 ; Set Counter to 6 to int after 250 ticks
OUT TCNT0,rmpr
IN rmpr,SREG ; Save status register
INC rtckl
BRNE TOvf0a
INC rtckh
TOvf0a:
CPI rtckl,LOW(ticks) ; End of second reached?
BRNE TOvf0b
CPI rtckh,HIGH(ticks)
BRNE TOvf0b
SBR rdtf,mEos ; Set End of second flag
CLR rtckl
CLR rtckh
TOvf0b:
INC rDcfl ; DCF77 counter tick
BRNE TOvf0c
DEC rDcfl
TOvf0c:
OUT SREG,rmpr ; Restore anything
POP rmpr
RETI
;
; Uart Rx Complete Interrupt
;
URxAv:
PUSH rmpr ; Save mpr register
IN rmpr,SREG ; Save SREG
PUSH rmpr
SBIC USR,FE ; Framing error?
RJMP URxAv2
IN rmpr,UDR ; Read Char
SBRC rsioflg,bEcho
RCALL siotxch ; Echo character
CPI rmpr,cBs ; Backspace?
BRNE URxAv0
CPI XL,RxBuF+1 ; Backspace
BRCS URxAv3
DEC XL
RJMP URxAv3
URxAv0:
ST X+,rmpr ; Store in RX buffer
CPI XL,RxBuL+1 ; End of buffer reached?
BRCS URxAv1
LDI XL,RxBuF
URxAv1:
CPI rmpr,cCr ; End of input line?
BRNE URxAv3
SBR rSioFlg,mRxCmp ; Set Line complete flag
RJMP URxAv3
URxAv2:
IN rmpr,UDR ; Clear Framing error bit
URxAv3:
POP rmpr ; Restore SREG
OUT SREG,rmpr
POP rmpr ; Restore rmpr
RETI
;
; Uart Data register empty interrupt
;
UTxDe:
PUSH rmpr ; Save register
IN rmpr,SREG ; Save status register
PUSH rmpr
CP YL,rsiotxin ; Compare Buffer In and Out
BRNE UTxDeCh
UTxDeOff:
CBR rSioFlg,mTxBAct ; No more chars to send
RJMP UTxDeRet
UTxDeCh:
SBIC PortB,bIRts ; RTS input ready?
RJMP UTxDeOff
LD rmpr,Y+ ; Read char
OUT UDR,rmpr
CPI YL,TxBuL+1 ; Check end of buffer
BRCS UTxDeRet
LDI YL,TxBuF ; Point to buffer start
UTxDeRet:
POP rmpr ; Restore status register
OUT SREG,rmpr
POP rmpr ; Restore register
RETI
;
; Uart Tx complete interrupt
;
UTxCp:
PUSH rmpr
IN rmpr,SREG
CBR rsioflg,mTxAct ; Clear the flag (not used here)
OUT SREG,rmpr
POP rmpr
RETI
;
; Analog comparator interrupt
;
AnaCp:
RETI
;
; ******* End of interrupt service routines ***********
;
; Sio service subroutines to be called from various sources
;
;
; Char in rmpr to Tx-Buffer
;
siotxch:
SBIC PortB,bIRts ; Send only, if RTS is active
RET
PUSH ZH
PUSH ZL
CLR ZH ; Point to TX buffer input position
MOV ZL,rSioTxIn
ST Z+,rmpr
CPI ZL,TxBuL+1 ; End of buffer reached?
BRCS siotxchx
LDI ZL,TxBuF
siotxchx: ; Wait here to avoid buffer overrun
CP ZL,YL
BREQ siotxchx
CLI ; Enter critical situation, disable interrupts
SBRC rsioflg,bTxBAct
RJMP sioTxChy
SBR rsioflg,mTxBAct
OUT UDR,rmpr
RJMP sioTxChn
sioTxChy:
MOV rsioTxIn,ZL
sioTxChn:
SEI ; End of critical situation
POP ZL
POP ZH
CPI rmpr,cCr ; Add linefeeds after carriage return?
BRNE sioTxChz
SBRS rsioflg,bAddLf
RJMP sioTxChz
LDI rmpr,cLf
RCALL sioTxCh
LDI rmpr,cCr
sioTxChz:
RET
;
; Transmits a null-terminated text from memory that Z points to
;
TxTxt:
PUSH rlpm
PUSH rmpr
TxTxt1:
LPM ; Read a char from the program memory at Z
MOV rmpr,rlpm
CPI rmpr,cnul ; End of text?
BREQ TxTxtz
RCALL siotxch
ADIW ZL,1
RJMP TxTxt1
TxTxtz:
POP rmpr
POP rlpm
RET
;
; Send date/time to SIO
;
DispDT:
RCALL DcfErr
CLR ZH ; Send time info in SRAM to SIO
LDI ZL,sDTF
DispDT1:
LD rmpr,Z+ ; Read from SRAM
RCALL siotxch ; Transmit
CPI rmpr,cCr ; Last char?
BRNE DispDT1
RET
;
; Send a byte as decimal number to the SIO
;
DispByte:
RCALL siotxch ; preface
LDI rmpr,' '
RCALL siotxch
LDI rmpr,'='
RCALL siotxch
LDI rmpr,' '
RCALL siotxch
LDI ZH,100 ; send 100's
SUB ZL,ZH
BRCS DispByte1
LDI rmpr,'1'
SUB ZL,ZH
BRCS DispByte1
SUB ZL,ZH
INC rmpr
DispByte1:
RCALL siotxch
ADD ZL,ZH
LDI ZH,10 ; send 10's
SUB ZL,ZH
BRCS DispByte3
LDI rmpr,'0'
DispByte2:
INC rmpr
SUB ZL,ZH
BRCC DispByte2
RJMP DispByte4
DispByte3:
CPI rmpr,' '
BREQ DispByte4
LDI rmpr,'0'
DispByte4:
ADD ZL,ZH
RCALL siotxch
LDI rmpr,'0' ; send 1's
ADD rmpr,ZL
RCALL siotxch
LDI rmpr,' '
RCALL siotxch
RJMP siotxch
; ************** End of SIO subrourines *******************
;
; ***************** Various subroutines *******************
;
; DT mode active, display date/time
;
DTModeX:
SBRS rdtf,bMin ; Minutes only?
RJMP DTModeX1
LDS rmpr,sSec ; End of minute?
CPI rmpr,'0'
BRNE DTModeX2
LDS rmpr,sSecT
CPI rmpr,'0'
BRNE DTModeX2
DTModeX1:
RCALL DispDT ; Display date and time
DTModeX2:
RET ; Return to loop
;
; DCF mode active, display DCF characteristics
;
DCFModeX:
RCALL DcfErr ; Report any DCF77 errors first
SBRC rdtf,bDcfCtm
RJMP DCFModeX2
OR rDcfs,rDcfs ; Report DCF signals bitwise
LDI rmpr,cCr
BREQ DCFModeX1
DEC rDcfLc
LDI rmpr,'1'
CP rDcfLc,rDcfCmp
BRCC DCFModeX1
DEC rmpr
DCFModeX1:
RJMP siotxch
DCFModeX2:
LDI rmpr,'b' ; Report signal number
MOV ZL,rDcfs
RCALL DispByte
LDI rmpr,'c' ; Report detected signal length in ticks
MOV ZL,rDcfLc
RCALL DispByte
LDI rmpr,'m' ; Report current discriminating value
MOV ZL,rDcfCmp
RCALL DispByte
LDI rmpr,cCr
RJMP siotxch
;
; Reports any DCF errors
;
DcfErr:
SBRS rDcfErr,bDcfEtr ; Any unreported errors?
RET
CBR rDcfErr,mDcfEtr
LDI ZH,HIGH(2*TxtDcfErr) ; Error text intro
LDI ZL,LOW(2*TxtDcfErr)
RCALL TxTxt
MOV rmpr,rDcfErr
ANDI rmpr,0x3F
DcfErr1:
ADIW ZL,1
CLC ; Identify next error bit
ROR rmpr
BRCC DcfErr3
RCALL TxTxt
DcfErr2:
OR rmpr,rmpr ; No more bits set?
BRNE DcfErr1
ANDI rDcfErr,0x80
LDI rmpr,cCr
RJMP siotxch
DcfErr3:
ADIW ZL,1 ; Point to next text sequence
LPM
OR rlpm,rlpm
BRNE DcfErr3
RJMP DcfErr2
;
; DCF synchronisation
;
Dcf:
CLR rDcfs ; End of minute, clear bit counter
SBR rDcfErr,(mDcfSOk | mDcfEtr) ; Set synch to be reported
LDI rmpr,'0'
CLR ZH
LDI ZL,sSec ; Second
ST Z,rmpr
ST -Z,rmpr
DEC ZL
DEC ZL
MOV rmpr,rDcf1 ; Minute
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf2 ; Tens of minutes
ROR rmpr
MOV rmpr,rDcf1
ROR rmpr
ROR rmpr
SWAP rmpr
ANDI rmpr,0x07
ORI rmpr,0x30
ST -Z,rmpr
DEC ZL ; Hour
MOV rmpr,rDcf2
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST -Z,rmpr
MOV rmpr,rDcf2 ; Tens of hours
ROL rmpr
ROL rmpr
ROL rmpr
ANDI rmpr,0x03
ORI rmpr,0x30
ST -Z,rmpr
LDI ZL,sDTF+dDD ; Day
MOV rmpr,rDcf3
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf3 ; Tens of Days
ROR rmpr
SWAP rmpr
ANDI rmpr,0x03
ORI rmpr,0x30
ST -Z,rmpr
ADIW ZL,4 ; Month
MOV rmpr,rDcf4
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf4 ; Tens of monthes
SWAP rmpr
ROR rmpr
ROR rmpr
ANDI rmpr,0x01
ORI rmpr,0x30
ST -Z,rmpr
ADIW ZL,6 ; Years
MOV rmpr,rDcf4
ROL rmpr
MOV rmpr,rDcf5
ROL rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf5 ; Tens of years
ROL rmpr
SWAP rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST -Z,rmpr
RET
;
; Next second
;
ChkDcf:
; Check DCF77 info complete
CBR rdtf,mEos ; Clear seconds flag bit
SBRC rdtf,bDcfOk ; Last DCF tick was ok?
RJMP NewDcfSec
SBR rdtf,mDcfSync ; Minute is over
MOV rmpr,rDcfs ; Have all 59 DCF ticks been received?
CPI rmpr,59
BRCS CntTooShort ; Less than 59 ticks
BRNE CountTooLong ; More than 59 ticks
SBRS rDcfErr,bDcfAny ; Any errors in parity?
RJMP Dcf
RJMP CntReset ; No DCF synch, clear all
CountTooLong:
SBRS rdtf,bDcfm ; DCF echo mode on?
RJMP CntReset
SBR rDcfErr,(mDcfCtl | mDcfEtr | mDcfAny) ; Set DCF error
type
RJMP CntReset
CntTooShort:
SBR rDcfErr,mDcfCts ; Set DCF error type
OR rDcfs,rDcfs ; DCF shift register totally empty?
BREQ CntReset
SBR rDcfErr,(mDcfEtr | mDcfAny) ; Set error to report
CntReset:
CLR rDcfs ; Clear the DCF shift counter
CBR rDcfErr,mDcfAny ; Clear the global DCF error bit
NewDcfSec:
CBR rdtf,mDcfOk ; Clear the DCF tick ok bit
IncSec:
CLR ZH ; Point to Date/Time info in SRAM
LDI ZL,sDTF+dTS ; Second
RCALL IncNmbr ; Next second and handle overflow
CPI rmpr,60 ; end of minute?
BRCC IncMin
IncRet:
RET
IncMin:
LDI rmpr,'0' ; Clear seconds
ST Z,rmpr
ST -Z,rmpr
LDI ZL,sDTF+dTM ; Next minute
RCALL IncNmbr
CPI rmpr,60 ; End of the hour?
BRCS IncRet
IncHour:
LDI rmpr,'0' ; Clear minutes
ST Z,rmpr
ST -Z,rmpr
LDI ZL,sDTF+dTH ; Next hour
RCALL IncNmbr
CPI rmpr,24 ; End of the day?
BRCS IncRet
LDI rmpr,'0' ; Clear hours
ST Z,rmpr
ST -Z,rmpr
IncDay:
LDI ZL,sDTF+dDD ; Next day
RCALL IncNmbr
CPI rmpr,32 ; End of month?
BRCC IncMonth
CPI rmpr,31 ; End of month for short monthes
BRNE ChkFeb
LDI ZL,sDTF+dDM ; Get days
RCALL GetByte
SUBI rmpr,4 ; Before April?
BRCS IncRet
CPI rmpr,3 ; April or June?
BRCS IncDay1
INC rmpr ; Later than June
IncDay1:
SBRC rmpr,0 ; Even month?
RET
RJMP IncMonth ; End of a short month
ChkFeb:
LDI ZL,sDTF+dDM ; Get current month
RCALL GetByte
CPI rmpr,2 ; February?
BRNE IncRet
LDI ZL,sDTF+dDY ; Get year
RCALL GetByte
ANDI rmpr,0x03 ; February with 29 days?
BRNE ChkFeb1
LDI ZL,sDTF+dDD ; Get current day
RCALL GetByte
CPI rmpr,30 ; Long February ends with 29
RJMP ChkFeb2
ChkFeb1:
LDI ZL,sDTF+dDD ; Short February, get actual day
RCALL GetByte
CPI rmpr,29 ; End of month?
ChkFeb2:
BRCS IncRet
IncMonth:
LDI ZL,sDTF+dDD ; Next month, clear days
LDI rmpr,'1'
ST Z,rmpr
LDI rmpr,'0'
ST -Z,rmpr
LDI ZL,sDTF+dDM ; Next month
RCALL IncNmbr
CPI rmpr,13 ; End of the year?
BRCS IncRet
IncYear:
LDI rmpr,'1' ; next year, clear month
ST Z,rmpr
LDI rmpr,'0'
ST -Z,rmpr
LDI ZL,sDTF+dDY ; Inc years by running into the following
;
; Inc Number at Z and Z-1 and return with the number in one byte
;
IncNmbr:
LD rmpr,Z ; Inc's a number in SRAM and its tens, if necessary
INC rmpr
CPI rmpr,'9'+1
BRCS IncNmbr1
LD rmpr,-Z
INC rmpr
ST Z+,rmpr
LDI rmpr,'0'
IncNmbr1:
ST Z,rmpr
;
; Get byte from Z and Z-1
;
GetByte:
LD rmpr,-Z ; Two digit number to binary, load first digit
SUBI rmpr,'0'
MOV rlpm,rmpr ; Multiply by 10
ADD rmpr,rmpr
ADD rmpr,rmpr
ADD rmpr,rlpm
ADD rmpr,rmpr
MOV rlpm,rmpr ; Store result in rlpm
INC ZL ; Add second digit
LD rmpr,Z
SUBI rmpr,'0'
ADD rmpr,rlpm
RET
; **************** End of the subroutine section ***************
;
; ******************** Main program loop ***********************
;
; Main program routine starts here
;
Start:
CLI ; Disable interrupts
LDI rmpr,RAMEND ; Set stack pointer
OUT SPL,rmpr
RCALL InitDT ; Init Date/Time-Info in SRAM
RCALL InitIo ; Init the I/O properties
RCALL InitSio ; Init the SIO properties
RCALL InitDcf
RCALL InitTimer0 ; Init the timer 0
RCALL InitAna ; Init the Analog comparator
; General Interrupt Mask Register
; External Interrupt Request 1 Enable
; External Interrupt Request 0 Enable
LDI rmpr,0b11000000

http://www.avr-asm-tutorial.net/avr_de/dcf77uhr.html (1 of 2)1/20/2009 7:37:53 PM


DCF77 Uhr mit dem AVR-Controller AT90S2313

OUT GIMSK,rmpr
; Timer/Counter Interrupt register
; Disable all TC1 Ints
; Enable TC0 Ints
LDI rmpr,0b00000010
OUT TIMSK,rmpr
; Enable interrupts (Master Int Enable)
SEI ; Enable all interrupts
; Master Control register settings
; Sleep Enable, Sleep Mode = Idle
; Ext Int 1 on rising edges
; Ext Int 0 on falling edges
LDI rmpr,0b00101110
OUT MCUCR,rmpr
Loop:
SLEEP ; Sleep until interrupt occurs
NOP ; needed to wakeup
SBRS rdtf,bDcfRdy ; Check if DCF signal has ended
RJMP ChkEos ; no, inc the seconds
CBR rdtf,mDcfRdy ; DCF: clear active signal ended
MOV rDcfLc,rDcfCnt
CP rDcfCmp,rDcfLc ; Count parity information, is it a 1 or a
0?
BRCC DcfPar
INC rDcfp ; Count 1's
DcfPar:
CPI rDcfs,21 ; Start of minute information?
BRCS DcfCrct
BRNE DcfPar1
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar1:
CPI rDcfs,29 ; Minute parity to check?
BRNE DcfPar2
SBRC rDcfp,0 ; Parity even?
SBR rDcfErr,(mDcfPem | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar2:
CPI rDcfs,36 ; Hour parity to check?
BRNE DcfPar3
SBRC rDcfp,0 ; Even?
SBR rDcfErr,(mDcfPeh | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar3:
CPI rDcfs,59 ; Date parity to check?
BRNE DcfCrct
SBRC rDcfp,0 ; Even?
SBR rDcfErr,(mDcfPed | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear Parity counter
DcfCrct:
CP rDcfCmp,rDcfLc ; Compare DCF signal length with medium
value
ROR rDcf5 ; Shift the result into the DCF 40-bit storage
ROR rDcf4
ROR rDcf3
ROR rDcf2
ROR rDcf1
SBR rdtf,mDcfOk ; Set the DCF signal ok bit
SUB rDcfCnt,rDcfCmp ; Calc distance of signal length from
medium value
BRCS DcfCrct0 ; Underflow = short pulse?
MOV rDcfL1,rDcfCnt ; Store this difference in the 1-length-
byte
MOV rmpr,rDcfL0 ; Has ever a 0-signal been received?
CPI rmpr,0
BRNE DcfCrct2
DcfCrctUp:
INC rDcfCmp ; Only 1-signals received so far, adjust higher
medium
RJMP Loop
DcfCrct0:
COM rDcfCnt ; Underflow = Signal 0, negative to positive
distance
MOV rDcfL0,rDcfCnt ; Store the difference in the 0-length-
byte
OR rDcfl1,rDcfL1 ; Has ever been received a 1-signal?
BRNE DcfCrCt2
DcfCrctDwn:
DEC rDcfCmp ; All 0's, reduce medium value
RJMP Loop
DcfCrct2:
CP rDcfL1,rDcfL0 ; Compare the differences of the last 0
and 1 received
BREQ Loop
BRCS DcfCrctDwn ; Adjust the medium value according to the
difference
RJMP DcfCrctUp
ChkEos:
SBRS rdtf,bEos ; End of a timer second?
RJMP Loop2
RCALL ChkDcf ; Check if DCF is to sychronize
SBRS rDTf,bDTm ; DT mode active?
RJMP Loop1
RCALL DTModeX ; Output the results
ModeOff:
CPI XL,RxBuF ; In the time- and dcf-echo-mode only blanks
are to be
BREQ Loop ; reacted upon. Has a char been sent over the SIO?
CLR XH ; Reset RX-buffer to the start
LDI XL,RxBuF
LD rmpr,X ; Read character
CPI rmpr,' ' ; Check for BLANK
BRNE StartLoop
BLD rsioflg,bEcho ; Restore the echo bit
CBR rDTf,(mDTm | mDcfm) ; Clear the mode bits
RJMP CursorOn ; send cursor on the SIO
Loop1:
SBRS rdtf,bDcfm ; DCF mode active?
RJMP Loop2
RCALL DCFModeX ; DCF mode execution
RJMP ModeOff
Loop2:
SBRS rSioFlg,bRxCmp ; Line of chars from the SIO complete?
RJMP Loop
CBR rSioFlg,mRxCmp ; Clear line available bit
SBI PortB,bOCts ; Set hardware CTS off
CPI XL,RxBuF+1 ; Has only a carriage return been sent?
BRNE Cmnd
LDI ZH,HIGH(2*TxtIntro) ; Empty line, transmit help text
LDI ZL,LOW(2*TxtIntro)
RCALL TxTxt
CursorOn:
LDI ZH,HIGH(2*TxtCursor) ; Display cursor line again
LDI ZL,LOW(2*TxtCursor)
RCALL TxTxt
CLR XH ; Set SIO-RX buffer to start
LDI XL,RxBuF
CBI PortB,bOCts ; Set hardware clear to send active
StartLoop:
RJMP Loop
Cmnd:
LDI ZH,HIGH(2*CmdTab) ; Line received, search for command in
table
LDI ZL,LOW(2*CmdTab)
Cmnd1:
CLR XH ; Receive buffer to start
LDI XL,RxBuF
Cmnd2:
LPM ; Read a char from the command table
ADIW ZL,1
LDI rmpr,cCr ; end of the command?
CP rmpr,rlpm
BRNE Cmnd4
LPM ; next byte in command table a Carriage return char?
CP rmpr,rlpm
BRNE Cmnd3
ADIW ZL,1 ; Jump over that
Cmnd3:
LPM ; Load the command adress from the tabel and push it to
the stack
ADIW ZL,1
PUSH rlpm
LPM
ADIW ZL,1
PUSH rlpm
LDI ZH,HIGH(2*TxtYellow) ; Set terminal to different color
LDI ZL,LOW(2*TxtYellow)
RJMP TxTxt ; after transmit the return jumps to the command
adress!
Cmnd4:
LD rmpr,X+ ; compare the next char in the RX buffer
CP rmpr,rlpm
BREQ Cmnd2 ; equal, compare next
Cmnd5:
LDI rmpr,cCr ; not equal, search for next command in table
CP rmpr,rlpm ; search end of the current command name
BREQ Cmnd6
LPM ; read until a carriage return in the command table is
found
ADIW ZL,1
RJMP Cmnd5
Cmnd6:
LPM ; read over additional carriage returns
CP rmpr,rlpm
BRNE Cmnd7
ADIW ZL,1
RJMP Cmnd6
Cmnd7:
ADIW ZL,2 ; ignore the following word (command adress)
LPM
LDI rmpr,cnul ; check if the end of tabel is reached
CP rmpr,rlpm
BRNE Cmnd1
LDI ZH,HIGH(2*TxtError) ; end of table, command is unknown
LDI ZL,LOW(2*TxtError)
RCALL TxTxt
RJMP CursorOn ; receive next command line
; ************************* End of program loop *****************
;
; ********************** Initialisation routines ****************
;
; Init the Date/Time-Info in the SRAM
;
InitDT:
LDI ZH,HIGH(2*DfltDT) ; Point Z to default value in program
memory
LDI ZL,LOW(2*DfltDT)
CLR XH ; Point X to date/time info in SRAM
LDI XL,sDTF
CLR rmpr ; Test for NUL = end of default?
InitDT1:
LPM ; Read from program memory
ADIW ZL,1 ; Inc Z pointer
CP rmpr,rlpm ; Test for end
BRNE InitDT2
RET
InitDT2:
ST X+,rlpm ; Copy to SRAM location and inc X pointer
RJMP InitDT1 ; Next location
;
; Initialize the IO-properties
;
InitIo:
; Pins on Port D used:
; Bit 0: Input RxD Sio
; 1: Output TxD Sio
; 2: Input External interrupt 0, DCF signal
; 3: Input External Interrupt 1, DCF signal
; 4: Output TO, not used
; 5: Output T1, not used
; 6: ICP Input Capture Pin, not used
LDI rmpr,0b00110010 ; Port D Control
OUT DDRD,rmpr ; Data direction register
LDI rmpr,0b00001100 ; Pullup resistors on DCF input on to
avoid glitches
OUT PortD,rmpr ; on open inputs
; Pins on Port B:
; Bit 0: Input AIN2, not used
; 1: Input AIN1, not used
; 2: Input SIO incoming RTS signal
; 3: Output OC1, not used
; 4: Output SIO outgoing CTS signal
; 5: Input MOSI, programming interface
; 6: Input MISO, programming interface
; 7: Input SCK, programming interface
LDI rmpr,0b00011000 ; Port B Control
OUT DDRB,rmpr ; Data Direction Register
LDI rmpr,0b00000000 ; No pullup resistors
OUT PortB,rmpr
RET
;
; Initialize the SIO properties
;
InitSio:
LDI rsioflg,0b00000011 ; Echo on, insert LF after CR on
CLR XH ; Set Rx Buffer
LDI XL,RxBuF
LDI rmpr,TxBuF ; Set Tx Buffer In
MOV rsiotxin,rmpr
CLR YH ; Set Tx Buffer Out
LDI YL,TxBuF
LDI rmpr,bddiv ; Init baud generator
OUT UBRR,rmpr ; set divider in UART baud rate register
LDI rmpr,0b00011000 ; Enable TX and RX, disable Ints
LDI ZL,0 ; Wait for 65 ms
LDI ZH,0
InitSio1:
SBIW ZL,1
BRNE InitSio1
LDI rmpr,0b11111000 ; Enable TX und RX 8 Bit and Ints
OUT UCR,rmpr ; in UART Control Register
CBI PortB,bOCts ; Set Clear to sent active
RET
;
; Init the Timer 0
;
InitTimer0:
CLR rmpr ; Stop the Timer
OUT TCCR0,rmpr
LDI rmpr,6 ; Start with 6 to get 250 steps @ 10 MHz and
div=64
OUT TCNT0,rmpr ; to Timer register
CLR rtckl ; Clear the low-level-ticker
CLR rtckh
CLR rdtf ; Clear the flags
LDI rmpr,3 ; Divide Clock by 64
OUT TCCR0,rmpr ; to Timer 0 Control register
RET
;
; Init the Analog comparator
;
InitAna:
; Analog comparator is disabled and switched off
LDI rmpr,0b00000000
OUT ACSR,rmpr
RET
;
; Init DCF
;
InitDcf:
LDI rmpr,cDcfCmpDflt ; Set medium value to default value
MOV rDcfCmp,rmpr
CLR rDcfL0 ; Clear the distances
CLR rDcfL1
CLR rDcfErr ; Clear the error flags
RET
; *************** End of init routines *********************
;
; ********************* Commands ***************************
;
; Command Table, holds the command text and the command adress
;
CmdTab:
.DB '?',cCr ; Display list of commands
.DW Help
.DB 'd','?',cCr,cCr
.DW DateOut
.DB 'd','s',cCr,cCr ; Mode echo seconds
.DW DS
.DB 'd','m',cCr,cCr ; Mode echo minutes
.DW DM
.DB 'd','a','t','e','=',cCr ; Set Date
.DW Date
.DB 't','i','m','e','=',cCr ; Set Time
.DW Time
.DB 'd','c','f','b',cCr,cCr ; Enter DCF bit pattern mode
.DW DCFMode
.DB 'd','c','f','c',cCr,cCr ; Enter DCF counter mode
.DW DCFCntMode
.DB cnul,cnul,cnul,cnul
;
; Display list of commands
Help:
LDI ZH,HIGH(2*TxtHelp)
LDI ZL,LOW(2*TxtHelp)
RCALL TxTxt
RJMP CursorOn
; Display date and time
DateOut:
RCALL DispDT
RJMP CursorOn
; Set mode to echo date and time every second
DS:
CBR rdtf,mMin
RCALL DTMode
RJMP CursorOn
; Set mode to echo date and time every minute only
DM:
SBR rdtf,mMin
; Enter Date/Time-Echo-Mode
DTMode:
SBR rdtf,mDTm ; Set the mode bit
LDI ZH,HIGH(2*TxtDtm) ; Display the info text
LDI ZL,LOW(2*TxtDtm)
SetMode:
RCALL TxTxt
BST rsioflg,bEcho ; Store the echo bit and switch it off
CBR rsioflg,mEcho
CBI PortB,bOCts ; Clear to send active to receive characters
CLR XH ; Set RX-buffer to start
LDI XL,RxBuF
RJMP Loop
;
; Enter DCFMode
;
DCFMode:
CBR rdtf,mDcfCtm ; clear the mode bit
DCFMode1:
SBR rdtf,mDcfm ; set echo mode
LDI ZH,HIGH(2*TxtDcf) ; Display the info text
LDI ZL,LOW(2*TxtDcf)
RJMP SetMode
;
; Enter DCF counter echo mode
;
DCFCntMode:
SBR rdtf,mDcfCtm ; set the DCF echo mode bit
RJMP DCFMode1
;
; Set date
;
Date:
CLR ZH ; Point Z to Date in SRAM
LDI ZL,sDTF
Date1:
LD rmpr,X+ ; Take over char from Rx-buffer
CPI rmpr,cCr
BREQ Date2
ST Z+,rmpr
LD rmpr,Z ; End reached?
CPI rmpr,','
BREQ Date2
CPI rmpr,cCr
BRNE Date1
Date2:
RCALL DispDT ; send date and time to SIO
RJMP CursorOn ; Cursor on and back to loop
;
; Set time
;
Time:
CLR ZH ; Point Z to Time in SRAM
LDI ZL,sDTT
RJMP Date1
;
; Texts to be displayed
;
TxtIntro:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Set screen
colours
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB "Hello world!"
.DB ccr,'T'
.DB "his is the experimental 2313 board (C)DG4FAC at work. ? for
help. "
.DB cnul,cnul
TxtCursor:
.DB ccr,cesc,'[','3','2','m','*','>',cesc,'[','3','6','m',cnul
TxtYellow:
.DB cesc,'[','3','3','m',cnul
TxtError:
.DB ccr,cesc,'[','3','1','m'
.DB "Error! Unknown command! "
.DB cCr,cnul
TxtHelp:
.DB "List of commands"
.DB ':',cCr
.DB " d?: Display date/time."
.DB cCr,' '
.DB " date=dd.yy.yyyy: Set date"
.DB '.',cCr
.DB " time=hh:mm:ss: Set time."
.DB cCr,' '
.DB " ds: Display seconds"
.DB '.',cCr
.DB " dm: Display minutes."
.DB cCr,' '
.DB " dcfb: DCF77 bit pattern echo."
.DB cCr,' '
.DB " dcfc: DCF77 counter echo."
.DB cCr,' '
.DB " ?: Display this list."
.DB cCr,cNul
TxtDtm:
.DB "Date/Time echo. SPACE to leave"
.DB '.',cesc,'[','3','5','m',cCr,cnul
TxtDcf:
.DB "DCF echo mode. SPACE to leave."
.DB cesc,'[','3','4','m',cCr,cnul,cnul
TxtDcfErr:
.DB ' ',' ','D','C','F',':',' ',cNul
.DB "Minutes wrong!"
.DB ' ',cNul
.DB "Hours wrong!"
.DB ' ',cNul
.DB "Date wrong"
.DB '!',cNul
.DB "Count too short!"
.DB ' ',cNul
.DB "Count too long"
.DB '!',cNul
.DB "Synchronisation."
.DB cNul,cNul
;
; Default date and time
;
DfltDT:
.DB "11.01.2001, 23:12:58"
.DB cCr,cNul
;
; End of code segment
;
; 1015 words, only a few left in the 2313. Enough for a copyright.
;
Copyright:
.DB " 2C00 1GDF4CA"

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/dcf77uhr.html (2 of 2)1/20/2009 7:37:53 PM


http://www.avr-asm-tutorial.net/avr_de/quellen/dcf77uhr.asm

; ***************************************************************
; * DCF-synchronized Digital Clock for RS232 communication on *
; * a 2313-Experimental-Board, Version 0.2 as of 12.01.2001 *
; * Features: XTal driven digital clock for exact date and time *
; * information, adjusted and read over a SIO-I/O 9k6 8N1 *
; * connection, Self-adjusting date- and time-synchronisation *
; * to a connected receiver for the Frankfurt/Germany based *
; * official clock reference DCF77 (optional) *
; * (C)2001 by Gerhard Schmidt *
; * report bugs to info@avr-asm-tutorial.net *
; ***************************************************************
;
; Hardware requirements:
; - 2313 board (see extra doc)
; - RS232 compatible terminal, e.g. PC+Win+HyperTerminal to adjust/read
; the date and time informationen
; - (RXD/TXD, RTS/CTS)-crosswired RS232 cable connection between the
; 2313-board and the terminal
; - Optional: DCF77 clock with active low receiver signal (second ticks)
;
; Software features:
; - Interrupt-driven and buffered SIO-I/O with RTS/CTS hardware protocol
; - Interrupt-driven clock signals with exact timing
; - SLEEP mode for reduced power consumption of the MPU
; - Exact date calculation from 2001 up to the year 2099
; - Transmits ANSI color codes for terminal control
; - DCF synchronisation: self-adjusting to unexact signal lengthes and
; spurious signals by software, loss-of-signal-detection, full parity bit
; checking, convenient hardware debugging opportunities by terminal display
; of the signal length and all detected errors during the sampling process
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2313def.inc"
.LIST
;
; Constants
;
; Constants for Sio properties
.EQU fq=10000000; Xtal frequency on board in Hz
.EQU baud=9600; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.EQU ticks=fq/16000; ticks per second for the timing functions
; Constants for Sio communications
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cBs=0x08; Backspace character
; Bit assignment of the RTS and CTS pins on Port B
.EQU bIRts = 2
.EQU bOCts = 4
; Locations in the Internal SRAM
.EQU sDTF = 0x60 ; Date/Time information, first location in SRAM
.EQU dDDT = 0 ; relative distance, Tens of Days
.EQU dDD = 1 ; relative distance, Days
.EQU dDMT = 3 ; relative distance, Tens of Monthes
.EQU dDM = 4 ; relative distance, Month
.EQU dDY = 9 ; relative distance, Years
.EQU dTHT = 12 ; relative disance, Tens of Hours
.EQU dTH = 13 ; relative distance, Hours
.EQU dTMT = 15 ; relative distance, Tens of Minutes
.EQU dTM = 16 ; relative distance, Minutes
.EQU dTST = 18 ; relative distance, Tens of Seconds
.EQU dTS = 19 ; relative distance, Seconds
.EQU sDTL = 0x74 ; Date/Time information, last location in SRAM
.EQU sDTT = 0x6C ; Position of Time
.EQU sSec = 0x73 ; Adress of seconds
.EQU sSecT = 0x72 ; Adress of tens of seconds
.EQU sMin = 0x70 ; Adress of minutes
; Constants for Sio Rx- and Tx-Buffers
.EQU RxBuF = 0x75 ; Sio Rx-Buffer, first location in SRAM
.EQU RxBuL = 0x84 ; Sio Rx-Buffer, last location in SRAM (16 Bytes)
.EQU TxBuF = 0x85 ; Sio Tx-Buffer, first location in SRAM
.EQU TxBuL = 0xA4 ; Sio Tx-Buffer, last location in SRAM (32 Bytes)
;
; Used registers
;
; Register mainly for Program Memory Read Operations
.DEF rlpm = R0 ; Used for read operations with LPM
; SIO Tx Buffer In pointer
.DEF rsiotxin = R1
; Registers for the DCF77-Receiver option
.DEF rdcfp = R2 ; Parity bit counter for DCF signals
.DEF rdcf1 = R3 ; Last Receiver Shift Register
.DEF rdcf2 = R4 ; Receiver Shift register
.DEF rdcf3 = R5 ; Receiver Shift register
.DEF rdcf4 = R6 ; Receiver Shift register
.DEF rdcf5 = R7 ; First Receiver Shift Register
.DEF rDcfCmp = R8 ; Compare length of DCF pulse (self-adjusted)
.DEF rDcfLc = R9 ; Last count length detected
.EQU cDcfCmpDflt = 125 ; Default length for DCF signals (self-adjusted)
.DEF rDcfCnt = R10 ; DCF length count, interrupt driven
.DEF rDcfL0 = R11 ; Distance of last short pulse from medium count length
.DEF rDcfL1 = R12 ; Distance of last long pulse from medium count length
; For all purposes
.DEF rmpr = R16 ; Multi-purpose register
; Low level ticker for seconds counting by interrupt (1.6 ms)
.DEF rtckh = R17 ; MSB
.DEF rtckl = R18 ; LSB
; DCF77 Tick register for signal length, driven by timer interrupt (1.6 ms)
.DEF rDcfl = R19
; Timer 0 flag register with the following bits:
.DEF rdtf = R20 ; Date/Time Flag register
.EQU bEos = 0 ; Bit 0: End of second reached
.EQU mEos = 1
.EQU bMin = 1 ; Bit 1: Echo minutes only
.EQU mMin = 2
.EQU bDTm = 2 ; Bit 2: DT mode active
.EQU mDTm = 4
; Bits used by DCF77:
.EQU bDcfm = 3 ; Bit 3: DCF mode active
.EQU mDcfm = 8
.EQU bDcfCtm = 4 ; Bit 4: DCF echo counters
.EQU mDcfCtm = 16
.EQU bDcfSync = 5 ; Bit 5: DCF synch tickers at next second
.EQU mDcfSync = 32
.EQU bDcfRdy = 6 ; Bit 6: DCF bit ready
.EQU mDcfRdy = 64
.EQU bDcfOk = 7 ; Bit 7: DCF Signal is ok
.EQU mDcfOk = 128
; SIO flag register
; Bit 5: Unused
; Bit 6: Unused
; Bit 7: Unused
.DEF rsioflg = R21 ; SIO flag register
.EQU bEcho = 0 ; Bit 0: Echo all incoming characters
.EQU mEcho = 1
.EQU bAddLf = 1 ; Bit 1: Insert LF after CR
.EQU mAddLf = 2
.EQU bTxBAct = 2 ; Bit 2: Transmitter buffer active
.EQU mTxBAct = 4
.EQU bTxAct = 3 ; Bit 3: Character transmission active
.EQU mTxAct = 8
.EQU bRxCmp = 4 ; Bit 4: Rx-Line complete
.EQU mRxCmp = 16
; DCF error flag register
.DEF rDcfErr = R22 ; Last DCF-error
.EQU bDcfPem = 0 ; Bit 0: Parity error minute
.EQU mDcfPem = 1
.EQU bDcfPeh = 1 ; Bit 1: Parity error hour
.EQU mDcfPeh = 2
.EQU bDcfPed = 2 ; Bit 2: Parity error date
.EQU mDcfPed = 4
.EQU bDcfCts = 3 ; Bit 3: Count too short
.EQU mDcfCts = 8
.EQU bDcfCtl = 4 ; Bit 4: Count too long
.EQU mDcfCtl = 16
.EQU bDcfSok = 5 ; Bit 5: Synchronisation ( not an error!)
.EQU mDcfSOk = 32
.EQU bDcfEtr = 6 ; Bit 6: Error to be reported
.EQU mDcfEtr = 64
.EQU bDcfAny = 7 ; Bit 7: Any error
.EQU mDcfAny = 128
; DCF shift register counter
.DEF rDcfs = R23 ; Shift Register Bit Counter
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-vectors
;
rjmp Start ; Reset-vector
rjmp IInt0 ; External Interrupt Request 0
rjmp IInt1 ; External Interrupt Request 1
rjmp TCpt1 ; Timer/Counter1 Capture event
rjmp TCmp1 ; Timer/Counter1 Compare match
rjmp TOvf1 ; Timer/Counter1 Overflow
rjmp TOvf0 ; Timer/Counter0 Overflow
rjmp URxAv ; Uart Rx char available
rjmp UTxDe ; Uart Tx data register empty
rjmp UTxCp ; Uart Tx complete
rjmp AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0: Started by a negative edge on the DCF input
;
IInt0:
push rmpr
in rmpr,SREG
sbrs rdtf,bDcfSync
rjmp IInt01
cbr rdtf,mDcfSync ; Synchronize DCF and internal tickers
clr rtckl
clr rtckh
IInt01:
clr rDcfl
out SREG,rmpr
pop rmpr
reti
;
; External Interrupt 1 : Started by a positive edge on the DCF input
;
IInt1:
push rmpr
in rmpr,SREG
cpi rDcfl,10 ; Exclude short signals
brcs IInt1r
mov rDcfCnt,rDcfl ; Store count length
inc rDcfs
sbr rdtf,mDcfRdy ; Flag received bit ready
IInt1r:
out SREG,rmpr
pop rmpr
reti
;
; Timer/Counter 1, Capture event interrupt, not used
;
TCpt1:
reti
;
; Timer/Counter 1, Compare match interrupt, not used
;
TCmp1:
reti
;
; Timer/Counter 1, Overflow interrupt, not used
;
TOvf1:
reti
;
; Timer/Counter 0, Overflow interrupt, used to count times
;
TOvf0:
push rmpr ; Save Register rmpr
ldi rmpr,6 ; Set Counter to 6 to int after 250 ticks
out TCNT0,rmpr
in rmpr,SREG ; Save status register
inc rtckl
brne TOvf0a
inc rtckh
TOvf0a:
cpi rtckl,LOW(ticks) ; End of second reached?
brne TOvf0b
cpi rtckh,HIGH(ticks)
brne TOvf0b
sbr rdtf,mEos ; Set End of second flag
clr rtckl
clr rtckh
TOvf0b:
inc rDcfl ; DCF77 counter tick
brne TOvf0c
dec rDcfl
TOvf0c:
out SREG,rmpr ; Restore anything
pop rmpr
reti
;
; Uart Rx Complete Interrupt
;
URxAv:
push rmpr ; Save mpr register
in rmpr,SREG ; Save SREG
push rmpr
sbic USR,FE ; Framing error?
rjmp URxAv2
in rmpr,UDR ; Read Char
sbrc rsioflg,bEcho
rcall siotxch ; Echo character
cpi rmpr,cBs ; Backspace?
brne URxAv0
cpi XL,RxBuF+1 ; Backspace
brcs URxAv3
dec XL
rjmp URxAv3
URxAv0:
st X+,rmpr ; Store in RX buffer
cpi XL,RxBuL+1 ; End of buffer reached?
brcs URxAv1
ldi XL,RxBuF
URxAv1:
cpi rmpr,cCr ; End of input line?
brne URxAv3
sbr rSioFlg,mRxCmp ; Set Line complete flag
rjmp URxAv3
URxAv2:
in rmpr,UDR ; Clear Framing error bit
URxAv3:
pop rmpr ; Restore SREG
out SREG,rmpr
pop rmpr ; Restore rmpr
reti
;
; Uart Data register empty interrupt
;
UTxDe:
push rmpr ; Save register
in rmpr,SREG ; Save status register
push rmpr
cp YL,rsiotxin ; Compare Buffer In and Out
brne UTxDeCh
UTxDeOff:
cbr rSioFlg,mTxBAct ; No more chars to send
rjmp UTxDeRet
UTxDeCh:
sbic PortB,bIRts ; RTS input ready?
rjmp UTxDeOff
ld rmpr,Y+ ; Read char
out UDR,rmpr
cpi YL,TxBuL+1 ; Check end of buffer
brcs UTxDeRet
ldi YL,TxBuF ; Point to buffer start
UTxDeRet:
pop rmpr ; Restore status register
out SREG,rmpr
pop rmpr ; Restore register
reti
;
; Uart Tx complete interrupt
;
UTxCp:
push rmpr
in rmpr,SREG
cbr rsioflg,mTxAct ; Clear the flag (not used here)
out SREG,rmpr
pop rmpr
reti
;
; Analog comparator interrupt
;
AnaCp:
reti
;
; ******* End of interrupt service routines ***********
;
; Sio service subroutines to be called from various sources
;
;
; Char in rmpr to Tx-Buffer
;
siotxch:
sbic PortB,bIRts ; Send only, if RTS is active
ret
push ZH
push ZL
clr ZH ; Point to TX buffer input position
mov ZL,rSioTxIn
st Z+,rmpr
cpi ZL,TxBuL+1 ; End of buffer reached?
brcs siotxchx
ldi ZL,TxBuF
siotxchx:
; Wait here to avoid buffer overrun
cp ZL,YL
breq siotxchx
cli ; Enter critical situation, disable interrupts
sbrc rsioflg,bTxBAct
rjmp sioTxChy
sbr rsioflg,mTxBAct
out UDR,rmpr
rjmp sioTxChn
sioTxChy:
mov rsioTxIn,ZL
sioTxChn:
sei ; End of critical situation
pop ZL
pop ZH
cpi rmpr,cCr ; Add linefeeds after carriage return?
brne sioTxChz
sbrs rsioflg,bAddLf
rjmp sioTxChz
ldi rmpr,cLf
rcall sioTxCh
ldi rmpr,cCr
sioTxChz:
ret
;
; Transmits a null-terminated text from memory that Z points to
;
TxTxt:
push rlpm
push rmpr
TxTxt1:
lpm ; Read a char from the program memory at Z
mov rmpr,rlpm
cpi rmpr,cnul ; End of text?
breq TxTxtz
rcall siotxch
adiw ZL,1
rjmp TxTxt1
TxTxtz:
pop rmpr
pop rlpm
ret
;
; Send date/time to SIO
;
DispDT:
rcall DcfErr
clr ZH ; Send time info in SRAM to SIO
ldi ZL,sDTF
DispDT1:
ld rmpr,Z+ ; Read from SRAM
rcall siotxch ; Transmit
cpi rmpr,cCr ; Last char?
brne DispDT1
ret
;
; Send a byte as decimal number to the SIO
;
DispByte:
rcall siotxch ; preface
ldi rmpr,' '
rcall siotxch
ldi rmpr,'='
rcall siotxch
ldi rmpr,' '
rcall siotxch
ldi ZH,100 ; send 100's
sub ZL,ZH
brcs DispByte1
ldi rmpr,'1'
sub ZL,ZH
brcs DispByte1
sub ZL,ZH
inc rmpr
DispByte1:
rcall siotxch
add ZL,ZH
ldi ZH,10 ; send 10's
sub ZL,ZH
brcs DispByte3
ldi rmpr,'0'
DispByte2:
inc rmpr
sub ZL,ZH
brcc DispByte2
rjmp DispByte4
DispByte3:
cpi rmpr,' '
breq DispByte4
ldi rmpr,'0'
DispByte4:
add ZL,ZH
rcall siotxch
ldi rmpr,'0' ; send 1's
add rmpr,ZL
rcall siotxch
ldi rmpr,' '
rcall siotxch
rjmp siotxch
; ************** End of SIO subrourines *******************
;
; ***************** Various subroutines *******************
;
; DT mode active, display date/time
;
DTModeX:
sbrs rdtf,bMin ; Minutes only?
rjmp DTModeX1
lds rmpr,sSec ; End of minute?
cpi rmpr,'0'
brne DTModeX2
lds rmpr,sSecT
cpi rmpr,'0'
brne DTModeX2
DTModeX1:
rcall DispDT ; Display date and time
DTModeX2:
ret ; Return to loop
;
; DCF mode active, display DCF characteristics
;
DCFModeX:
rcall DcfErr ; Report any DCF77 errors first
sbrc rdtf,bDcfCtm
rjmp DCFModeX2
or rDcfs,rDcfs ; Report DCF signals bitwise
ldi rmpr,cCr
breq DCFModeX1
dec rDcfLc
ldi rmpr,'1'
cp rDcfLc,rDcfCmp
brcc DCFModeX1
dec rmpr
DCFModeX1:
rjmp siotxch
DCFModeX2:
ldi rmpr,'b' ; Report signal number
mov ZL,rDcfs
rcall DispByte
ldi rmpr,'c' ; Report detected signal length in ticks
mov ZL,rDcfLc
rcall DispByte
ldi rmpr,'m' ; Report current discriminating value
mov ZL,rDcfCmp
rcall DispByte
ldi rmpr,cCr
rjmp siotxch
;
; Reports any DCF errors
;
DcfErr:
sbrs rDcfErr,bDcfEtr ; Any unreported errors?
ret
cbr rDcfErr,mDcfEtr
ldi ZH,HIGH(2*TxtDcfErr) ; Error text intro
ldi ZL,LOW(2*TxtDcfErr)
rcall TxTxt
mov rmpr,rDcfErr
andi rmpr,0x3F
DcfErr1:
adiw ZL,1
clc ; Identify next error bit
ror rmpr
brcc DcfErr3
rcall TxTxt
DcfErr2:
or rmpr,rmpr ; No more bits set?
brne DcfErr1
andi rDcfErr,0x80
ldi rmpr,cCr
rjmp siotxch
DcfErr3:
adiw ZL,1 ; Point to next text sequence
lpm
or rlpm,rlpm
brne DcfErr3
rjmp DcfErr2
;
; DCF synchronisation
;
Dcf:
clr rDcfs ; End of minute, clear bit counter
sbr rDcfErr,(mDcfSOk | mDcfEtr) ; Set synch to be reported
ldi rmpr,'0'
clr ZH
ldi ZL,sSec ; Second
st Z,rmpr
st -Z,rmpr
dec ZL
dec ZL
mov rmpr,rDcf1 ; Minute
ror rmpr
ror rmpr
andi rmpr,0x0F
ori rmpr,0x30
st Z,rmpr
mov rmpr,rDcf2 ; Tens of minutes
ror rmpr
mov rmpr,rDcf1
ror rmpr
ror rmpr
swap rmpr
andi rmpr,0x07
ori rmpr,0x30
st -Z,rmpr
dec ZL ; Hour
mov rmpr,rDcf2
ror rmpr
ror rmpr
andi rmpr,0x0F
ori rmpr,0x30
st -Z,rmpr
mov rmpr,rDcf2 ; Tens of hours
rol rmpr
rol rmpr
rol rmpr
andi rmpr,0x03
ori rmpr,0x30
st -Z,rmpr
ldi ZL,sDTF+dDD ; Day
mov rmpr,rDcf3
ror rmpr
andi rmpr,0x0F
ori rmpr,0x30
st Z,rmpr
mov rmpr,rDcf3 ; Tens of Days
ror rmpr
swap rmpr
andi rmpr,0x03
ori rmpr,0x30
st -Z,rmpr
adiw ZL,4 ; Month
mov rmpr,rDcf4
ror rmpr
ror rmpr
andi rmpr,0x0F
ori rmpr,0x30
st Z,rmpr
mov rmpr,rDcf4 ; Tens of monthes
swap rmpr
ror rmpr
ror rmpr
andi rmpr,0x01
ori rmpr,0x30
st -Z,rmpr
adiw ZL,6 ; Years
mov rmpr,rDcf4
rol rmpr
mov rmpr,rDcf5
rol rmpr
andi rmpr,0x0F
ori rmpr,0x30
st Z,rmpr
mov rmpr,rDcf5 ; Tens of years
rol rmpr
swap rmpr
andi rmpr,0x0F
ori rmpr,0x30
st -Z,rmpr
ret
;
; Next second
;
ChkDcf:
; Check DCF77 info complete
cbr rdtf,mEos ; Clear seconds flag bit
sbrc rdtf,bDcfOk ; Last DCF tick was ok?
rjmp NewDcfSec
sbr rdtf,mDcfSync ; Minute is over
mov rmpr,rDcfs ; Have all 59 DCF ticks been received?
cpi rmpr,59
brcs CntTooShort ; Less than 59 ticks
brne CountTooLong ; More than 59 ticks
sbrs rDcfErr,bDcfAny ; Any errors in parity?
rjmp Dcf
rjmp CntReset ; No DCF synch, clear all
CountTooLong:
sbrs rdtf,bDcfm ; DCF echo mode on?
rjmp CntReset
sbr rDcfErr,(mDcfCtl | mDcfEtr | mDcfAny) ; Set DCF error type
rjmp CntReset
CntTooShort:
sbr rDcfErr,mDcfCts ; Set DCF error type
or rDcfs,rDcfs ; DCF shift register totally empty?
breq CntReset
sbr rDcfErr,(mDcfEtr | mDcfAny) ; Set error to report
CntReset:
clr rDcfs ; Clear the DCF shift counter
cbr rDcfErr,mDcfAny ; Clear the global DCF error bit
NewDcfSec:
cbr rdtf,mDcfOk ; Clear the DCF tick ok bit
IncSec:
clr ZH ; Point to Date/Time info in SRAM
ldi ZL,sDTF+dTS ; Second
rcall IncNmbr ; Next second and handle overflow
cpi rmpr,60 ; end of minute?
brcc IncMin
IncRet:
ret
IncMin:
ldi rmpr,'0' ; Clear seconds
st Z,rmpr
st -Z,rmpr
ldi ZL,sDTF+dTM ; Next minute
rcall IncNmbr
cpi rmpr,60 ; End of the hour?
brcs IncRet
IncHour:
ldi rmpr,'0' ; Clear minutes
st Z,rmpr
st -Z,rmpr
ldi ZL,sDTF+dTH ; Next hour
rcall IncNmbr
cpi rmpr,24 ; End of the day?
brcs IncRet
ldi rmpr,'0' ; Clear hours
st Z,rmpr
st -Z,rmpr
IncDay:
ldi ZL,sDTF+dDD ; Next day
rcall IncNmbr
cpi rmpr,32 ; End of month?
brcc IncMonth
cpi rmpr,31 ; End of month for short monthes
brne ChkFeb
ldi ZL,sDTF+dDM ; Get days
rcall GetByte
subi rmpr,4 ; Before April?
brcs IncRet
cpi rmpr,3 ; April or June?
brcs IncDay1
inc rmpr ; Later than June
IncDay1:
sbrc rmpr,0 ; Even month?
ret
rjmp IncMonth ; End of a short month
ChkFeb:
ldi ZL,sDTF+dDM ; Get current month
rcall GetByte
cpi rmpr,2 ; February?
brne IncRet
ldi ZL,sDTF+dDY ; Get year
rcall GetByte
andi rmpr,0x03 ; February with 29 days?
brne ChkFeb1
ldi ZL,sDTF+dDD ; Get current day
rcall GetByte
cpi rmpr,30 ; Long February ends with 29
rjmp ChkFeb2
ChkFeb1:
ldi ZL,sDTF+dDD ; Short February, get actual day
rcall GetByte
cpi rmpr,29 ; End of month?
ChkFeb2:
brcs IncRet
IncMonth:
ldi ZL,sDTF+dDD ; Next month, clear days
ldi rmpr,'1'
st Z,rmpr
ldi rmpr,'0'
st -Z,rmpr
ldi ZL,sDTF+dDM ; Next month
rcall IncNmbr
cpi rmpr,13 ; End of the year?
brcs IncRet
IncYear:
ldi rmpr,'1' ; next year, clear month
st Z,rmpr
ldi rmpr,'0'
st -Z,rmpr
ldi ZL,sDTF+dDY ; Inc years by running into the following
;
; Inc Number at Z and Z-1 and return with the number in one byte
;
IncNmbr:
ld rmpr,Z ; Inc's a number in SRAM and its tens, if necessary
inc rmpr
cpi rmpr,'9'+1
brcs IncNmbr1
ld rmpr,-Z
inc rmpr
st Z+,rmpr
ldi rmpr,'0'
IncNmbr1:
st Z,rmpr
;
; Get byte from Z and Z-1
;
GetByte:
ld rmpr,-Z ; Two digit number to binary, load first digit
subi rmpr,'0'
mov rlpm,rmpr ; Multiply by 10
add rmpr,rmpr
add rmpr,rmpr
add rmpr,rlpm
add rmpr,rmpr
mov rlpm,rmpr ; Store result in rlpm
inc ZL ; Add second digit
ld rmpr,Z
subi rmpr,'0'
add rmpr,rlpm
ret
; **************** End of the subroutine section ***************
;
; ******************** Main program loop ***********************
;
; Main program routine starts here
;
Start:
cli ; Disable interrupts
ldi rmpr,RAMEND ; Set stack pointer
out SPL,rmpr
rcall InitDT ; Init Date/Time-Info in SRAM
rcall InitIo ; Init the I/O properties
rcall InitSio ; Init the SIO properties
rcall InitDcf
rcall InitTimer0 ; Init the timer 0
rcall InitAna ; Init the Analog comparator
; General Interrupt Mask Register
; External Interrupt Request 1 Enable
; External Interrupt Request 0 Enable
ldi rmpr,0b11000000
out GIMSK,rmpr
; Timer/Counter Interrupt register
; Disable all TC1 Ints
; Enable TC0 Ints
ldi rmpr,0b00000010
out TIMSK,rmpr
; Enable interrupts (Master Int Enable)
sei ; Enable all interrupts
; Master Control register settings
; Sleep Enable, Sleep Mode = Idle
; Ext Int 1 on rising edges
; Ext Int 0 on falling edges
ldi rmpr,0b00101110
out MCUCR,rmpr
Loop:
sleep ; Sleep until interrupt occurs
nop ; needed to wakeup
sbrs rdtf,bDcfRdy ; Check if DCF signal has ended
rjmp ChkEos ; no, inc the seconds
cbr rdtf,mDcfRdy ; DCF: clear active signal ended
mov rDcfLc,rDcfCnt
cp rDcfCmp,rDcfLc ; Count parity information, is it a 1 or a 0?
brcc DcfPar
inc rDcfp ; Count 1's
DcfPar:
cpi rDcfs,21 ; Start of minute information?
brcs DcfCrct
brne DcfPar1
clr rDcfp ; Clear parity counter
rjmp DcfCrct
DcfPar1:
cpi rDcfs,29 ; Minute parity to check?
brne DcfPar2
sbrc rDcfp,0 ; Parity even?
sbr rDcfErr,(mDcfPem | mDcfEtr | mDcfAny) ; Parity error
clr rDcfp ; Clear parity counter
rjmp DcfCrct
DcfPar2:
cpi rDcfs,36 ; Hour parity to check?
brne DcfPar3
sbrc rDcfp,0 ; Even?
sbr rDcfErr,(mDcfPeh | mDcfEtr | mDcfAny) ; Parity error
clr rDcfp ; Clear parity counter
rjmp DcfCrct
DcfPar3:
cpi rDcfs,59 ; Date parity to check?
brne DcfCrct
sbrc rDcfp,0 ; Even?
sbr rDcfErr,(mDcfPed | mDcfEtr | mDcfAny) ; Parity error
clr rDcfp ; Clear Parity counter
DcfCrct:
cp rDcfCmp,rDcfLc ; Compare DCF signal length with medium value
ror rDcf5 ; Shift the result into the DCF 40-bit storage
ror rDcf4
ror rDcf3
ror rDcf2
ror rDcf1
sbr rdtf,mDcfOk ; Set the DCF signal ok bit
sub rDcfCnt,rDcfCmp ; Calc distance of signal length from medium value
brcs DcfCrct0 ; Underflow = short pulse?
mov rDcfL1,rDcfCnt ; Store this difference in the 1-length-byte
mov rmpr,rDcfL0 ; Has ever a 0-signal been received?
cpi rmpr,0
brne DcfCrct2
DcfCrctUp:
inc rDcfCmp ; Only 1-signals received so far, adjust higher medium
rjmp Loop
DcfCrct0:
com rDcfCnt ; Underflow = Signal 0, negative to positive distance
mov rDcfL0,rDcfCnt ; Store the difference in the 0-length-byte
or rDcfl1,rDcfL1 ; Has ever been received a 1-signal?
brne DcfCrCt2
DcfCrctDwn:
dec rDcfCmp ; All 0's, reduce medium value
rjmp Loop
DcfCrct2:
cp rDcfL1,rDcfL0 ; Compare the differences of the last 0 and 1 received
breq Loop
brcs DcfCrctDwn ; Adjust the medium value according to the difference
rjmp DcfCrctUp
ChkEos:
sbrs rdtf,bEos ; End of a timer second?
rjmp Loop2
rcall ChkDcf ; Check if DCF is to sychronize
sbrs rDTf,bDTm ; DT mode active?
rjmp Loop1

http://www.avr-asm-tutorial.net/avr_de/quellen/dcf77uhr.asm (1 of 2)1/20/2009 7:38:01 PM


http://www.avr-asm-tutorial.net/avr_de/quellen/dcf77uhr.asm

rcall DTModeX ; Output the results


ModeOff:
cpi XL,RxBuF ; In the time- and dcf-echo-mode only blanks are to be
breq Loop ; reacted upon. Has a char been sent over the SIO?
clr XH ; Reset RX-buffer to the start
ldi XL,RxBuF
ld rmpr,X ; Read character
cpi rmpr,' ' ; Check for BLANK
brne StartLoop
bld rsioflg,bEcho ; Restore the echo bit
cbr rDTf,(mDTm | mDcfm) ; Clear the mode bits
rjmp CursorOn ; send cursor on the SIO
Loop1:
sbrs rdtf,bDcfm ; DCF mode active?
rjmp Loop2
rcall DCFModeX ; DCF mode execution
rjmp ModeOff
Loop2:
sbrs rSioFlg,bRxCmp ; Line of chars from the SIO complete?
rjmp Loop
cbr rSioFlg,mRxCmp ; Clear line available bit
sbi PortB,bOCts ; Set hardware CTS off
cpi XL,RxBuF+1 ; Has only a carriage return been sent?
brne Cmnd
ldi ZH,HIGH(2*TxtIntro) ; Empty line, transmit help text
ldi ZL,LOW(2*TxtIntro)
rcall TxTxt
CursorOn:
ldi ZH,HIGH(2*TxtCursor) ; Display cursor line again
ldi ZL,LOW(2*TxtCursor)
rcall TxTxt
clr XH ; Set SIO-RX buffer to start
ldi XL,RxBuF
cbi PortB,bOCts ; Set hardware clear to send active
StartLoop:
rjmp Loop
Cmnd:
ldi ZH,HIGH(2*CmdTab) ; Line received, search for command in table
ldi ZL,LOW(2*CmdTab)
Cmnd1:
clr XH ; Receive buffer to start
ldi XL,RxBuF
Cmnd2:
lpm ; Read a char from the command table
adiw ZL,1
ldi rmpr,cCr ; end of the command?
cp rmpr,rlpm
brne Cmnd4
lpm ; next byte in command table a Carriage return char?
cp rmpr,rlpm
brne Cmnd3
adiw ZL,1 ; Jump over that
Cmnd3:
lpm ; Load the command adress from the tabel and push it to the stack
adiw ZL,1
push rlpm
lpm
adiw ZL,1
push rlpm
ldi ZH,HIGH(2*TxtYellow) ; Set terminal to different color
ldi ZL,LOW(2*TxtYellow)
rjmp TxTxt ; after transmit the return jumps to the command adress!
Cmnd4:
ld rmpr,X+ ; compare the next char in the RX buffer
cp rmpr,rlpm
breq Cmnd2 ; equal, compare next
Cmnd5:
ldi rmpr,cCr ; not equal, search for next command in table
cp rmpr,rlpm ; search end of the current command name
breq Cmnd6
lpm ; read until a carriage return in the command table is found
adiw ZL,1
rjmp Cmnd5
Cmnd6:
lpm ; read over additional carriage returns
cp rmpr,rlpm
brne Cmnd7
adiw ZL,1
rjmp Cmnd6
Cmnd7:
adiw ZL,2 ; ignore the following word (command adress)
lpm
ldi rmpr,cnul ; check if the end of tabel is reached
cp rmpr,rlpm
brne Cmnd1
ldi ZH,HIGH(2*TxtError) ; end of table, command is unknown
ldi ZL,LOW(2*TxtError)
rcall TxTxt
rjmp CursorOn ; receive next command line
; ************************* End of program loop *****************
;
; ********************** Initialisation routines ****************
;
; Init the Date/Time-Info in the SRAM
;
InitDT:
ldi ZH,HIGH(2*DfltDT) ; Point Z to default value in program memory
ldi ZL,LOW(2*DfltDT)
clr XH ; Point X to date/time info in SRAM
ldi XL,sDTF
clr rmpr ; Test for NUL = end of default?
InitDT1:
lpm ; Read from program memory
adiw ZL,1 ; Inc Z pointer
cp rmpr,rlpm ; Test for end
brne InitDT2
ret
InitDT2:
st X+,rlpm ; Copy to SRAM location and inc X pointer
rjmp InitDT1 ; Next location
;
; Initialize the IO-properties
;
InitIo:
; Pins on Port D used:
; Bit 0: Input RxD Sio
; 1: Output TxD Sio
; 2: Input External interrupt 0, DCF signal
; 3: Input External Interrupt 1, DCF signal
; 4: Output TO, not used
; 5: Output T1, not used
; 6: ICP Input Capture Pin, not used
ldi rmpr,0b00110010 ; Port D Control
out DDRD,rmpr ; Data direction register
ldi rmpr,0b00001100 ; Pullup resistors on DCF input on to avoid glitches
out PortD,rmpr ; on open inputs
; Pins on Port B:
; Bit 0: Input AIN2, not used
; 1: Input AIN1, not used
; 2: Input SIO incoming RTS signal
; 3: Output OC1, not used
; 4: Output SIO outgoing CTS signal
; 5: Input MOSI, programming interface
; 6: Input MISO, programming interface
; 7: Input SCK, programming interface
ldi rmpr,0b00011000 ; Port B Control
out DDRB,rmpr ; Data Direction Register
ldi rmpr,0b00000000 ; No pullup resistors
out PortB,rmpr
ret
;
; Initialize the SIO properties
;
InitSio:
ldi rsioflg,0b00000011 ; Echo on, insert LF after CR on
clr XH ; Set Rx Buffer
ldi XL,RxBuF
ldi rmpr,TxBuF ; Set Tx Buffer In
mov rsiotxin,rmpr
clr YH ; Set Tx Buffer Out
ldi YL,TxBuF
ldi rmpr,bddiv ; Init baud generator
out UBRR,rmpr ; set divider in UART baud rate register
ldi rmpr,0b00011000 ; Enable TX and RX, disable Ints
ldi ZL,0 ; Wait for 65 ms
ldi ZH,0
InitSio1:
sbiw ZL,1
brne InitSio1
ldi rmpr,0b11111000 ; Enable TX und RX 8 Bit and Ints
out UCR,rmpr ; in UART Control Register
cbi PortB,bOCts ; Set Clear to sent active
ret
;
; Init the Timer 0
;
InitTimer0:
clr rmpr ; Stop the Timer
out TCCR0,rmpr
ldi rmpr,6 ; Start with 6 to get 250 steps @ 10 MHz and div=64
out TCNT0,rmpr ; to Timer register
clr rtckl ; Clear the low-level-ticker
clr rtckh
clr rdtf ; Clear the flags
ldi rmpr,3 ; Divide Clock by 64
out TCCR0,rmpr ; to Timer 0 Control register
ret
;
; Init the Analog comparator
;
InitAna:
; Analog comparator is disabled and switched off
ldi rmpr,0b00000000
out ACSR,rmpr
ret
;
; Init DCF
;
InitDcf:
ldi rmpr,cDcfCmpDflt ; Set medium value to default value
mov rDcfCmp,rmpr
clr rDcfL0 ; Clear the distances
clr rDcfL1
clr rDcfErr ; Clear the error flags
ret
; *************** End of init routines *********************
;
; ********************* Commands ***************************
;
; Command Table, holds the command text and the command adress
;
CmdTab:
.DB '?',cCr ; Display list of commands
.DW Help
.DB 'd','?',cCr,cCr
.DW DateOut
.DB 'd','s',cCr,cCr ; Mode echo seconds
.DW DS
.DB 'd','m',cCr,cCr ; Mode echo minutes
.DW DM
.DB 'd','a','t','e','=',cCr ; Set Date
.DW Date
.DB 't','i','m','e','=',cCr ; Set Time
.DW Time
.DB 'd','c','f','b',cCr,cCr ; Enter DCF bit pattern mode
.DW DCFMode
.DB 'd','c','f','c',cCr,cCr ; Enter DCF counter mode
.DW DCFCntMode
.DB cnul,cnul,cnul,cnul
;
; Display list of commands
Help:
ldi ZH,HIGH(2*TxtHelp)
ldi ZL,LOW(2*TxtHelp)
rcall TxTxt
rjmp CursorOn
; Display date and time
DateOut:
rcall DispDT
rjmp CursorOn
; Set mode to echo date and time every second
DS:
cbr rdtf,mMin
rcall DTMode
rjmp CursorOn
; Set mode to echo date and time every minute only
DM:
sbr rdtf,mMin
; Enter Date/Time-Echo-Mode
DTMode:
sbr rdtf,mDTm ; Set the mode bit
ldi ZH,HIGH(2*TxtDtm) ; Display the info text
ldi ZL,LOW(2*TxtDtm)
SetMode:
rcall TxTxt
bst rsioflg,bEcho ; Store the echo bit and switch it off
cbr rsioflg,mEcho
cbi PortB,bOCts ; Clear to send active to receive characters
clr XH ; Set RX-buffer to start
ldi XL,RxBuF
rjmp Loop
;
; Enter DCFMode
;
DCFMode:
cbr rdtf,mDcfCtm ; clear the mode bit
DCFMode1:
sbr rdtf,mDcfm ; set echo mode
ldi ZH,HIGH(2*TxtDcf) ; Display the info text
ldi ZL,LOW(2*TxtDcf)
rjmp SetMode
;
; Enter DCF counter echo mode
;
DCFCntMode:
sbr rdtf,mDcfCtm ; set the DCF echo mode bit
rjmp DCFMode1
;
; Set date
;
Date:
clr ZH ; Point Z to Date in SRAM
ldi ZL,sDTF
Date1:
ld rmpr,X+ ; Take over char from Rx-buffer
cpi rmpr,cCr
breq Date2
st Z+,rmpr
ld rmpr,Z ; End reached?
cpi rmpr,','
breq Date2
cpi rmpr,cCr
brne Date1
Date2:
rcall DispDT ; send date and time to SIO
rjmp CursorOn ; Cursor on and back to loop
;
; Set time
;
Time:
clr ZH ; Point Z to Time in SRAM
ldi ZL,sDTT
rjmp Date1
;
; Texts to be displayed
;
TxtIntro:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Set screen colours
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB "Hello world!"
.DB ccr,'T'
.DB "his is the experimental 2313 board (C)DG4FAC at work. ? for help. "
.DB cnul,cnul
TxtCursor:
.DB ccr,cesc,'[','3','2','m','*','>',cesc,'[','3','6','m',cnul
TxtYellow:
.DB cesc,'[','3','3','m',cnul
TxtError:
.DB ccr,cesc,'[','3','1','m'
.DB "Error! Unknown command! "
.DB cCr,cnul
TxtHelp:
.DB "List of commands"
.DB ':',cCr
.DB " d?: Display date/time."
.DB cCr,' '
.DB " date=dd.yy.yyyy: Set date"
.DB '.',cCr
.DB " time=hh:mm:ss: Set time."
.DB cCr,' '
.DB " ds: Display seconds"
.DB '.',cCr
.DB " dm: Display minutes."
.DB cCr,' '
.DB " dcfb: DCF77 bit pattern echo."
.DB cCr,' '
.DB " dcfc: DCF77 counter echo."
.DB cCr,' '
.DB " ?: Display this list."
.DB cCr,cNul
TxtDtm:
.DB "Date/Time echo. SPACE to leave"
.DB '.',cesc,'[','3','5','m',cCr,cnul
TxtDcf:
.DB "DCF echo mode. SPACE to leave."
.DB cesc,'[','3','4','m',cCr,cnul,cnul
TxtDcfErr:
.DB ' ',' ','D','C','F',':',' ',cNul
.DB "Minutes wrong!"
.DB ' ',cNul
.DB "Hours wrong!"
.DB ' ',cNul
.DB "Date wrong"
.DB '!',cNul
.DB "Count too short!"
.DB ' ',cNul
.DB "Count too long"
.DB '!',cNul
.DB "Synchronisation."
.DB cNul,cNul
;
; Default date and time
;
DfltDT:
.DB "11.01.2001, 23:12:58"
.DB cCr,cNul
;
; End of code segment
;
; 1015 words, only a few left in the 2313. Enough for a copyright.
;
Copyright:
.DB " 2C00 1GDF4CA"

http://www.avr-asm-tutorial.net/avr_de/quellen/dcf77uhr.asm (2 of 2)1/20/2009 7:38:01 PM


http://www.avr-asm-tutorial.net/avr_gra/clock.gif

http://www.avr-asm-tutorial.net/avr_gra/clock.gif1/20/2009 7:38:04 PM
Experimental 2313 board (C)2001 DG4FAC

18pk 18pk
100
22µ 22µ nk XTal
100 + 10MHz
2k2 2k2 2k2 20 10 5 4
nk +
CD 16 15 6 2 RXD 2
1 PD0 1
DSR 6 Loop J1Normal DCF77-
RD INT0
O1 12
13 I1 3 PD2 6
RTS 7 2 PD1 2 Clock
TXD
14 O2 11 Data INT1
CTS 3 TD I2 PD3 7 3
8
DTR 8
MAX232 Loop J2Normal
O3 9
4 16
I3 PB4 4
9 CTS
7 O4
DS9 5 I4 10 Control
(Male)
RTS 14 PB2
1 3 4 5
+ +
22µ 22µ AT90S2313

18 PB6

9 MISO 19 PB7
10
SCK 17 PB5
8 7
RESET RESET
6 5
LED 1k 1
LED 1N4148
4 3
MOSI 1k
2 1
+ 270k
1µT
4 x 1N4001
~ 1
9 ... 15 V 330pK 330pK
~ 2 + 7805 +
470µ 35V 1µT

To PC Nullmodem-cable To Board
DSR
1 1
6 CD 6
RD RD
RTS 7 2 2 RTS
TD TD 3 7
CTS 3 CTS
8 8
4 4
9 DTR 9
DB9 5 GND
5 DB9
(Female) (Female)
Decoder für Fernsteuersignale, Quellcode

Pfad: Home => AVR-Übersicht => Anwendungen => PCM-Decoder => Quellcode

Assembler Quellcode für den PCM-Dekoder


;
*******************************************************************
; * PCM2PWG-Dekoder fuer AT90S2323, Version 0.4 vom 20.12.2000
*
; * Dekodiert PCM Pulse in pulsweitenmoduliertes Rechtecksignal
*
; * (C)2000 by info!at!avr-asm-tutorial.net
*
;
*******************************************************************
;
; Momentan eingestellt auf PCM-Signale von 800 bis 2200 µs und 4 MHz
; Taktfrequenz des Prozessors.
; Durch Anpassung der Konstanten unten kann der Code an andere
Signale
; angepasst werden.
;
; VCC LED PWG PCM PCM-Ein: 25ms = 40 Hz Frequenzeingang
; Aus Aus Ein positiv gepulste PCM-Signale
; +-8----7----6----5--+
; | | PWG-Aus: 1.4 ms = 714 Hz
Ausgangsfrequenz
; O AT 90 S 2323 | positiv gepulst fuer 0..1,4 ms
; | |
; +-1----2----3----4--+ LED-Aus: Ausgang auf Null, wenn Fehler
; RST XT1 XT2 GND
;
; ********* Eingangssignal PCM-kodiert ************************
;
; Phase I II III IV V VI VII
; PCM 1---- -------------------- ------
; Ein \\\\\ / \\\\\\\\\\\\ /
; 0------------ ------------------------
;
; ********* Ausgangssignal Pulsweite-Oszillator ***************
;
; PWG 1 ------------- ------
; Aus / \ /
; 0---- -------------
; Zeit µs |<--0..cCycl->|<-cCycl..0-->| 800 - 2200 µs:
; |<----------cCycl---------->| cCycl = 1400 µs
;
; *************************************************************
;
.NOLIST
.INCLUDE "2323def.inc"
.LIST
;
; Verwendete Register
;
.DEF rmpr = R16 ; Vielzweckregister
.DEF rdel = R17 ; Register fuer Verzoergerungsschleifen
.DEF rpwc = R18 ; Zaehler fuer den Pulsweiten-Generator
.DEF rpws = R19 ; Aktueller Ausgangswert fuer den Pulsweiten-
Generator
.DEF rpwn = R20 ; Naechster Wert fuer Pulsweiten-Generator
.DEF rtry = R21 ; Anzahl der zulaessigen Fehlversuche
.DEF rctr = R22 ; Zaehler fuer aktive Schleifen
.DEF rerr = R23 ; Anzahl Fehlversuche
; ZL = R30 and ZH = R31 werden fuer lange Zeitschleifen benutzt
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Port-Modus
.EQU bIn = 0 ; Eingangspin 0, positive Polaritaet
.EQU bOut = 1 ; Ausgabe fuer Pulsweitengenerator
.EQU bFail = 2 ; Ausgang fuer die Fehler-LED, aktiv Null
;
; Konstanten (1 Zyklus = 6 µs = 24 Taktzyklen bei 4 MHz)
;
; Anpassung der Quarzfrequenz an andere Taktfrequenzen des
Prozessors
;
.EQU cXtal = 4 ; Taktfrequenz in MHz
;
; Anpassung der Gesamtlaenge an andere Eingangssignale
;
.EQU cPulseDuration = 25000 ; Gesamtdauer des Eingangsimpulses in µs
;
; Anpassung der Zeiten an andere PCM-Pulsweiten
;
.EQU cMinPulse = 800 ; Minimum Pulsdauer in µs
.EQU cMaxPulse = 2200 ; Maximum Pulsdauer in µs
;
; Anpassung des Defaultwertes fuer den Pulsweiten-Generator bei
; Fehlsignalen oder Signalverlust, 0%: Ausgang wird Null, 100%:
; Ausgang wird dauerhaft Eins, 50%: Ausgang geht auf 50% Pulsweite
;
.EQU cFallBackValue = 50 ; 50% Pulsweite
;
; Die folgenden Werte werden automatisch aus den obigen Angaben
; ausgerechnet. Bitte nur aendern, wenn Du weisst was Du tust!
;
.EQU cUnitLength = 24 ; Taktzyklen pro Schleifendurchgang
.EQU cCycleLength = cUnitLength/cXtal ; Gesamtschleifendauer in µs
.EQU cCycl = cPulseDuration/cCycleLength ; Schleifen in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Aktive Schleifen
.EQU cTolerance = cStep/10; Tolerierte Frueh- und
Spaetschleifendauer
.EQU cMinSteps = cMinPulse/cCycleLength ; Schleifen bis zum
Zaehlbeginn
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Schleifen nach Zaehlende
.EQU cMin1 = cMinSteps-cTolerance-1 ; Mindestschleifen mit Eingang
hoch
.EQU cTlp = cTolerance-1 ; Fruehzeitige inaktive Schleifen,
toleriert
.EQU cTla = cTolerance ; Schleifen nach Ende der aktiven Zaehlzeit
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Schleifen mit inaktivem
Signal
.EQU cFbck = 1 ; Number of false signals to tolerate before default
is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default-Wert fuer den PWG
;
; Makros fuer den Error-LED-Ausgang (auf Aktiv low eingestellt)
;
.MACRO LedErrOn
CBI PortB,bFail
.ENDM
.MACRO LedErrOff
SBI PortB,bFail
.ENDM
;
; Makros fuer Verzoegerungen
;
.MACRO Delay1 ; Einzelschritt
NOP
.ENDM
;
.MACRO Delay2 ; Doppelschritt
NOP
NOP
.ENDM
;
.MACRO Delay3 ; Verzoegerung um Vielfache von je 3 Schritten
LDI rdel,@0
MD3:
DEC rdel
BRNE MD3
.ENDM
;
.MACRO Delay4 ; Verzoegerung um Vielfache von je 4 Schritten
LDI rdel,@0
MD4:
DEC rdel
NOP
BRNE MD4
.ENDM
;
.MACRO MacPwm ; Makro fuer den Pulsweiten-Generator
DEC rpwc ; 1 1 1 1
BREQ MAP2 ; 1 1 2 2
CP rpws,rpwc ; 1 1
BRCS MAP1 ; 1 2
NOP ; 1
CBI PortB,bOut; 2
RJMP MAP3 ; 2
MAP1:
SBI PortB,bOut; 2
RJMP MAP3 ; 2
MAP2:
MOV rpws,rpwn ; 1 1
LDI rpwc,cstep; 1 1
SBI PortB,bOut; 2 2
NOP ; 1 1
NOP ; 1 1
MAP3: ;-----------
; 9 9 9 9
;===========
.ENDM
;
; Beginn des Hauptprogrammes, initiere Variablen
;
Start:
LDI rpwc,cDflt ; Zaehler fuer den PWG
LDI rpws,cDflt ; Aktueller PWG-Wert
LDI rpwn,cDflt ; Naechster PWG-Wert

; Initiiere den Port B


;
LDI rmpr,pbmode ; Setze Datenrichtungsregister
OUT DDRB,rmpr ; von Port B
SBI PortB,bIn ; Schalte Pull-Up-Widerstand am Eingang an

; Starte Phase I : Warte bis der Eingang Null wird


;
; Schalte Fehler ein, bis das Signal korrekt ist
;
PH1:
MacPwm ; 9
LDI rerr,cFbck; 1
LDI rpwn,cDflt; 1
LedErrOn ; 2
Delay3(3) ; 9
;
; Setze maximale Zeitdauer fuer die Erkennung eines Null-Signals
;
PH1a:
LDI ZL,Low(cCycl); 1
LDI ZH,HIGH(cCycl);1
; ---
; 24
; ===
; Warte bis der Eingang Null ist oder Zeitueberlauf eintritt
;
PH1b:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH2 ; 2
SBIW ZL,1 ; 2 2
BREQ PH1c ; 1 2
Delay4(2) ; 8
RJMP PH1b ; 2
; ---
; 24
; ===
; Zeitueberlauf mit Eingang auf Eins
;
PH1c: ; (15)
Delay4(1) ; 4
;
; Fehler bei aktivem Eingang, zaehle die Fehler
;
PH1d: ;(19 19)
DEC rerr ; 1 1
BRNE PH1a ; 2 1
;
; Zu viele Fehler in Folge, setze Fehlerbedingung
;
Delay1 ; 1
RJMP PH1 ; 2
; ---
; 24
; ===
; Starte Phase II: Eingang ist Null, warte auf aktives Signal
;
PH2: ; (12)
Delay3(2) ; 6
Delay2 ; 2
RJMP PH2b ; 2
;
; Fehler aufgetreten, setze Fehlerbedingung
;
PH2a:
MacPwm ; 9
LDI rerr,cFbck; 1
LDI rpwn,cDflt; 1
LedErrOn ; 2
Delay3(3) ; 9
;
; Setze Zaehler fuer Zeitueberlauf bei inaktivem Eingang
;
PH2b: ; (22 22)
LDI ZL,LOW(cCycl); 1 1
LDI ZH,HIGH(cCycl); 1 1
; ------
; 24 24
; ======
; Warte bis der Eingang eins ist oder Zeitueberlauf passiert
;
PH2c:
MacPwm ; 9 9 9 9
SBIC PinB,bIn ; 2 2 2 1
RJMP PH3 ; 2
SBIW ZL,1 ; 2 2 2
BREQ PH2d ; 1 2 2
Delay4(2) ; 8
RJMP PH2c ; 2
; ---
; 24
; ===
; Zeitueberlauf bei inaktivem Eingang, zaehle Fehler
;
PH2d: ; (15 15)
Delay4(1) ; 4 4
PH2e: ; (19 19)
DEC rtry ; 1 1
BRNE PH2b ; 1 2
NOP ; 1
RJMP PH2a ; 2
; ---
; 24
; ===
; Phase III: Eingang ist aktiv geworden, warte cMin1 Schleifen, ob
stabil
;
PH3: ; (12)
Delay3(3) ; 9
Delay2 ; 2
LDI rtry,cMin1; 1
; ---
; 24
; ===
; Warte bis cMin1 Schleifen mit aktivem Eingang abgelaufen
;
PH3a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH3b ; 2
DEC rtry ; 1 1
BREQ PH4 ; 1 2
Delay3(3) ; 9
RJMP PH3a ; 2
; ---
; 24
; ===
; Fruehes Inaktivierung des Einganges, Fehler bei Eingang Null
;
PH3b: ; (12)
Delay3(1) ; 3
Delay2 ; 2
RJMP PH2e ; 2
;
; Phase IV: Eingang ist Eins fuer cMin1 Schleifen, starte
Toleranzzeit
;
PH4: ;(14)
Delay4(2) ; 8
LDI rtry,cTlp ; 1
LDI rctr,cstep; 1
; ---
; 24
; ===
; Warte fuer Toleranzzeit oder auf inaktiven Eingang
;
PH4a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rtry ; 1 1
BREQ PH5 ; 1 2
Delay3(3) ; 9
RJMP PH4a ; 2
; ---
; 24
; ===
;
; Phase V: Ende der Toleranzzeit, beginne Abwaertszaehlung
;
PH5: ; (14)
Delay4(2) ; 8
Delay2 ; 2
; ---
; 24
; ===
PH5a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rctr ; 1 1
BREQ PH6 ; 1 2
Delay3(3) ; 9
RJMP PH5a ; 2
; ---
; 24
; ===
; Phase VI: Ende des Abwaertszaehlens, toleriere Nachlaufzeit
;
PH6: ; (14)
Delay3(3) ; 9
LDI rtry,cTla ; 1
; ---
; 24
; ===
; Zeitueberlauf nach cTla Schleifen, beende bei Ueberlauf oder
inaktiv
;
PH6a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rtry ; 1 1
BREQ PH6b ; 1 2
Delay3(3) ; 9
RJMP PH6a ; 2
; ---
; 24
; ===
; Aktives Signal zu lang, Fehlerbedingung mit aktivem Eingang
;
PH6b: ; (14)
Delay3(1) ; 3
RJMP PH1d ; 2
;
; Phase VII: Eingang inaktiv, pruefe auf ausreichende inaktive Zeit
;
;
PH7: ; (12)
Delay4(2) ; 8
Delay2 ; 2
LDI ZL,LOW(cMin0); 1
LDI ZH,HIGH(cMin0); 1
; ---
; 24
; ===
PH7a:
MacPwm ; 9 9 9
SBIC PinB,bIn ; 2 2 1
RJMP PH7b ; 2
SBIW ZL,1 ; 2 2
BREQ PH7c ; 1 2
Delay4(2) ; 8
RJMP PH7a ; 2
; ---
; 24
; ===
; Fruehzeitiges Ende der Signalpause, Fehlerbedingung bei inaktivem
Eingang
;
PH7b: ; (12)
Delay3(1) ; 3
Delay2 ; 2
RJMP PH1d ; 2
;
; Ende der Mindestdauer des inaktiven Signals, setze neuen Messwert
;
PH7c: ; (15)
MOV rpwn,rctr ; 1
LDI rerr,cFbck; 1
LedErrOff ; 2
Delay1 ; 1
RJMP PH2b ; 2
;
; Ende des Programmes
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/pcm2pwg4.html1/20/2009 7:38:11 PM
Decoder für Fernsteuersignale

Pfad: Home => AVR-Übersicht => Anwendungen => PCM-Decoder

AVR-Einchip-Prozessoren
AT90Sxxxx
von ATMEL in praktischen Beispielen.

Decoder für Fernsteuersignale


1. Kurzfassung für Eilige
2. Aufbau von Fernsteuersignalen
3. Umwandlung von Fernsteuersignalen in eine analoge Stellgröße
4. Erforderliche Hardware
5. Programmaufbau

Kurzfassung für Eilige


Der Decoder wandelt pulslängenkodierte Fernsteuersignale am Eingang des AT90S2323-Prozessors
(Port-Bit 0, Pin 5) in ein pulsweiten-moduliertes Signal am Ausgang (Port-Bit 1, Pin 6) um. Durch
Filtern des pulsweiten-modulierten Ausgangssignals mit einem einfachen RC-Glied entsteht ein
Analogsignal, dessen Höhe linear mit der Pulsdauer des Eingangssignales ansteigt. Das Analogsignal
kann als Stellgröße für eine Rudermaschine dienen. Gehen falsche Eingangssignale (z.B. Störsignale)
am Eingang ein oder bleibt das Signal aus, dann wird das Ausgangssignal auf einen vordefinierbaren
Default-Wert gebracht. Am Port-Bit 2, Pin 7) kann zu Testzwecken, z.B. durch Anschließen einer
LED, festgestellt werden, ob das Eingangssignal korrekt erkannt wird.
Die vorliegende Fassung des Programmes ist für Signale von 0,8 bis 2,2 ms aktiver Dauer und 25 ms
Gesamtdauer eingestellt. Der Default-Wert wird schon beim ersten fehlerhaften Signal eingestellt.
Alle Parameter des Programmes können den jeweiligen Bedürfnissen angepasst werden. Dazu sind
nur die entsprechenden Zahlen im Quelltext zu ändern.
HTML-Format Quellcode-Format Flußdiagramm in GIF-Format Flußdigramm in PDF-Format
Schaltbild in PDF-Format Schaltbild in GIF-Format

Zum Anfang des Dokumentes

Aufbau von Fernsteuersignalen


Ein Fernsteuersignal muss eine analoge Größe (z.B. die Stellung eines Steuerknüppels) in ein
digitales Signal verschlüsseln, das dann beim Empfänger wieder in das analoge Signal
zurückgewandelt und mittels einer Rudermaschine ein anderes Gerät, z.B. ein Seitenruder, in die
richtige Stellung dreht.
Dazu wird die analoge Stellung beim Absender in eine Spannung umgewandelt (z.B. durch ein
Potentiometer) und diese in ein Rechtecksignal umgesetzt. Das Rechtecksignal variiert je nach Höhe
der Spannung seine Zeitdauer. Ist die Spannung Null, so dauert das Signal genau 0,8 Millisekunden
(ms). Ist die Spannung an der Vollaussteuerung, so dauert es 2,0 ms lang. Die Pulsdauer enthält also
die Information über die Stellgröße, die Information ist der Pulsdauer "aufmoduliert". Allgemein
nennt man solche Signale Puls-codierte Modulation oder PCM. Recht verschwenderisch ist die Zeit
zwischen zwei solchen aufeinanderfolgenden Pulsen bemessen: Zwei Pulsanfänge sind immer genau
25 ms auseinander, so dass beim längsten Puls von 2,2 ms genau 22,8 ms lang Pause ist. Ein
kontinuierlich anstehendes Fernsteuersignal hat deshalb die konstante Frequenz von 40 Hertz, also 40
Pulse pro Sekunde.
Das puls-codierte Signal, das entweder den Zustand Null (Pause) oder Eins (Puls) einnehmen kann,
wird dem Sender zugeführt. Dieser Sender sendet entweder auf einer Frequenz, wenn gerade Pause
ist, oder auf einer anderen Frequenz, wenn gerade Puls ist. Das PCM-Signal wird also im Sender in
ein frequenzmoduliertes Signal mit den beiden Sendefrequenzen f0 (Null) und f0+fm (Puls)
umgesetzt und als solches dann im Wechsel ausgesendet. Die beiden Frequenzen liegen dabei sehr
nah zusammen, so dass im Empfänger beide empfangen und gleichzeitig weiterverarbeitet werden.
Am Ende der Empfängs- und Hochfrequenz-Mimik im Empfänger unterscheidet dann doch eine
bestimmte Filterstufe, Demodulator genannt, ob die empfangene Frequenz f0 oder f0+fm ist und gibt
nach aussen ein entsprechendes digitales Signal zum Besten.

Zum Anfang des Dokumentes

Umwandlung in eine analoge Stellgröße


Damit kann natürlich noch keine Rudermaschine etwas anfangen, weil die Stellinformation ja in der
Länge des immer noch digitalen Pulses steckt und die Rudermaschine ein analoges Stellsignal
erwartet. Die Stufe dazwischen wäre also ein Puls-Code-Modulationssignal-zu-Analog-Stellsignal-
Wandler oder vielleicht etwas kürzer ein PCM-Demodulator. Solche Wandler hat man früher in
analoger Schaltungstechnik erbaut. Mehr oder weniger zuverlässig und mehr oder weniger
aufwendig, was die Zahl der Bauteile betrifft. Diese Zeiten sind vorbei, heute verwendet man dazu
einen ganzen Computer. Keinen Intel-PC, aber einen richtigen Computer mit Programmsteuerung,
Ein- und Ausgangsleitungen, RAM-Speicher, einem nichtflüchtigen EEPROM-Speicher und vielem
anderen mehr. Bloss halt keine Festplatte, aber das kommt später auch noch in das kleine achtpolige
IC hinein.
So ein Kleinst-Kleinst-Rechner im achtpoliger IC-Fassung, AT90S2323 genannt, hat einen Eingang,
an dem das Fernsteuersignal anliegt. Der mit einem Quarz oder einem Keramikschwinger getaktete
Rechner braucht nun nur noch mitzählen, für welchen Zeitraum das Pulssignal anliegt. Dann ist
rechnerintern klar, auf welche Größe die Rudermaschine eingestellt werden sollte. Die braucht aber
die Information in einer anderen Form, nämlich analog. Damit wir uns den entsprechenden DA-
Wandler sparen können, wird ein Ausgangspin dergestalt abwechselnd Null und Eins geschaltet, dass
an dem Pin im Mittel die richtige analoge Spannung anliegen würde. Das Signal wird mittels eines
Widerstandes auf einen Kondensator geleitet, der diese Mittelung vornimmt und ein wunderschönes
analoges Signal abgibt. Dies deshalb, weil er mit dem ständigen Aufladen und Entladen nicht
mitkommt und letztlich nur noch das Zeitverhältnis zwischen Nullen und Einsen anzeigt, das
Pulsverhältnis.
Die beiden Vorgänge, das Ausmessen des Pulses am Eingang und das Takten des Ausganges im
richtigen Pulsverhältnis, müssen sehr rasch und gleichmässig parallel erfolgen. Jede Verzögerung
oder Unterbrechung ist zu vermeiden, deshalb besteht die ganze Programmierkunst ausschließlich
darin, die entsprechenden Zählschleifen vom Timing her hinzukriegen. Jeder normale Rechner wäre
damit überfordert, weil er ständig unterbrochen und durch irgendwelchen User-Unsinn wie
Mausklicke aus dem Tritt kommt. Nicht so ein entsprechend nur mit diesen beiden Aufgaben
programmierter Rechner, der sonst nichts anderes zeitlich koordinieren muss.

Zum Anfang des Dokumentes

Erforderliche Hardware
Das Schaltbild des Decoders (auch als PDF-Datei verfügbar) sieht so aufgeräumt aus wie ein
Feinschmecker-Abendessen.

Der Quarz übernimmt die Zeitsteuerung des Rechners, die beiden Kondensatoren sorgen für das
zuverlässige Anschwingen des internen Taktgenerators. An Pin 1 des Rechners wird durch eine
Kombination von Widerstand und Kondensator ein zuverlässiges Reset-Signal für den Rechner
erzeugt, so dass auch nach Spikes auf der Versorgungsleitung der ganze Rechner sein Programm mit
Null beginnt und sich selbst in einem solchen üblen Fall von Einwirkung wieder fängt.
Das Eingangssignal wird über einen Widerstand von 1 k (hier nicht eingezeichnet) zugeführt, damit
es bei Überspannung nicht gleich das IC zerschießen kann. Das Ausgangssignal geht über den bereits
besprochenen Widerstand auf den Mittwertbildner-Kondensator. Der noch freie dritte Ein-/Ausgang
ist über einen Widerstand mit einer Leuchtdiode verbunden, die im Fehlerfall (wie z.B. zu kurze oder
zu lange Impulsdauer, mehrfaches Fehlen des Fernsteuersignals) anzeigt und nur für Testzwecke
dient. Im echten Betrieb kann die Beschaltung dieses Ausganges entfallen.

Zum Anfang des Dokumentes

Programmaufbau, Software
Die gesamte Software baut auf zeitsensitiven Schleifen auf und verwendet keine Interrupts.
HTML- Flußdiagramm in GIF- Flußdigramm in PDF-
Quellcode-Format
Format Format Format
Die Dauer des Pulses wird im vorliegenden Fall mit 233 Einzelstufen zu je 6 µs Dauer ermittelt, die
den Zeitraum von 0,8 bis 2 ms überdecken. Pulse, die geringfügig kürzer oder länger sind, werden
ohne Fehleranzeige noch als korrekt eingeordnet. Pulse, die deutlich kürzer als 0,8 ms sind (>10%
kürzer) oder deutlich länger als 2,2 ms sind, werden als fehlerhaft übergangen. Pausen, die deutlich
kürzer als vorgeschrieben dauern oder das Ausbleiben des Signales werden als Fehler interpretiert.
Nach einem mehrfachen Auftreten des Fehlers in nicht unterbrochener Folge über eine einstellbare
Zahl von Perioden hinaus wird ein vorher definierter Default-Wert (z.B. Null oder im vorliegenden
Fall die halbe Versorgungsspannung) eingestellt, so dass bei Signalfehlern schnell der sichere Wert
eingestellt wird.
Das Impuls-/Pausen-Verhältnis am Ausgang ist mit (2,2 - 0,8) = 1,4 ms entsprechend 714 Hz
getaktet. Lediglich bei bei Vollaussteuerung ist keine Frequenz messbar, da der Ausgang dauerhaft
auf High-Pegel liegt. Die Auflösung des Verhältnisses beträgt ebenfalls 233 Schritte, so dass ein
Fehler von max. 0,43% bei der Messung und bei der Analogwandlung eingehalten wird. Das dürfte
auch für High-Precision-Anwendungen tolerabel sein.

Zum Anfang des Dokumentes

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/remote.html1/20/2009 7:38:21 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/pcm2pwg4.asm

; *******************************************************************
; * PCM2PWG-Dekoder fuer AT90S2323, Version 0.4 vom 20.12.2000 *
; * Dekodiert PCM Pulse in pulsweitenmoduliertes Rechtecksignal *
; * (C)2000 by info@avr-asm-tutorial.net *
; *******************************************************************
;
; Momentan eingestellt auf PCM-Signale von 800 bis 2200 µs und 4 MHz
; Taktfrequenz des Prozessors.
; Durch Anpassung der Konstanten unten kann der Code an andere Signale
; angepasst werden.
;
; VCC LED PWG PCM PCM-Ein: 25ms = 40 Hz Frequenzeingang
; Aus Aus Ein positiv gepulste PCM-Signale
; +-8----7----6----5--+
; | | PWG-Aus: 1.4 ms = 714 Hz Ausgangsfrequenz
; O AT 90 S 2323 | positiv gepulst fuer 0..1,4 ms
; | |
; +-1----2----3----4--+ LED-Aus: Ausgang auf Null, wenn Fehler
; RST XT1 XT2 GND
;
; ********* Eingangssignal PCM-kodiert ************************
;
; Phase I II III IV V VI VII
; PCM 1---- -------------------- ------
; Ein \\\\\ / \\\\\\\\\\\\ /
; 0------------ ------------------------
;
; ********* Ausgangssignal Pulsweite-Oszillator ***************
;
; PWG 1 ------------- ------
; Aus / \ /
; 0---- -------------
; Zeit µs |<--0..cCycl->|<-cCycl..0-->| 800 - 2200 µs:
; |<----------cCycl---------->| cCycl = 1400 µs
;
; *************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2323def.inc"
.LIST
;
; Verwendete Register
;
.DEF rmpr = R16 ; Vielzweckregister
.DEF rdel = R17 ; Register fuer Verzoergerungsschleifen
.DEF rpwc = R18 ; Zaehler fuer den Pulsweiten-Generator
.DEF rpws = R19 ; Aktueller Ausgangswert fuer den Pulsweiten-Generator
.DEF rpwn = R20 ; Naechster Wert fuer Pulsweiten-Generator
.DEF rtry = R21 ; Anzahl der zulaessigen Fehlversuche
.DEF rctr = R22 ; Zaehler fuer aktive Schleifen
.DEF rerr = R23 ; Anzahl Fehlversuche
; ZL = R30 and ZH = R31 werden fuer lange Zeitschleifen benutzt
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Port-Modus
.EQU bIn = 0 ; Eingangspin 0, positive Polaritaet
.EQU bOut = 1 ; Ausgabe fuer Pulsweitengenerator
.EQU bFail = 2 ; Ausgang fuer die Fehler-LED, aktiv Null
;
; Konstanten (1 Zyklus = 6 µs = 24 Taktzyklen bei 4 MHz)
;
; Anpassung der Quarzfrequenz an andere Taktfrequenzen des Prozessors
;
.EQU cXtal = 4 ; Taktfrequenz in MHz
;
; Anpassung der Gesamtlaenge an andere Eingangssignale
;
.EQU cPulseDuration = 25000 ; Gesamtdauer des Eingangsimpulses in µs
;
; Anpassung der Zeiten an andere PCM-Pulsweiten
;
.EQU cMinPulse = 800 ; Minimum Pulsdauer in µs
.EQU cMaxPulse = 2200 ; Maximum Pulsdauer in µs
;
; Anpassung des Defaultwertes fuer den Pulsweiten-Generator bei
; Fehlsignalen oder Signalverlust, 0%: Ausgang wird Null, 100%:
; Ausgang wird dauerhaft Eins, 50%: Ausgang geht auf 50% Pulsweite
;
.EQU cFallBackValue = 50 ; 50% Pulsweite
;
; Die folgenden Werte werden automatisch aus den obigen Angaben
; ausgerechnet. Bitte nur aendern, wenn Du weisst was Du tust!
;
.EQU cUnitLength = 24 ; Taktzyklen pro Schleifendurchgang
.EQU cCycleLength = cUnitLength/cXtal ; Gesamtschleifendauer in µs
.EQU cCycl = cPulseDuration/cCycleLength ; Schleifen in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Aktive Schleifen
.EQU cTolerance = cStep/10; Tolerierte Frueh- und Spaetschleifendauer
.EQU cMinSteps = cMinPulse/cCycleLength ; Schleifen bis zum Zaehlbeginn
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Schleifen nach Zaehlende
.EQU cMin1 = cMinSteps-cTolerance-1 ; Mindestschleifen mit Eingang hoch
.EQU cTlp = cTolerance-1 ; Fruehzeitige inaktive Schleifen, toleriert
.EQU cTla = cTolerance ; Schleifen nach Ende der aktiven Zaehlzeit
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Schleifen mit inaktivem Signal
.EQU cFbck = 1 ; Number of false signals to tolerate before default is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default-Wert fuer den PWG
;
; Makros fuer den Error-LED-Ausgang (auf Aktiv low eingestellt)
;
.MACRO LedErrOn
cbi PortB,bFail
.ENDM
.MACRO LedErrOff
sbi PortB,bFail
.ENDM
;
; Makros fuer Verzoegerungen
;
.MACRO Delay1 ; Einzelschritt
nop
.ENDM
;
.MACRO Delay2 ; Doppelschritt
nop
nop
.ENDM
;
.MACRO Delay3 ; Verzoegerung um Vielfache von je 3 Schritten
ldi rdel,@0
MD3:
dec rdel
brne MD3
.ENDM
;
.MACRO Delay4 ; Verzoegerung um Vielfache von je 4 Schritten
ldi rdel,@0
MD4:
dec rdel
nop
brne MD4
.ENDM
;
.MACRO MacPwm ; Makro fuer den Pulsweiten-Generator
dec rpwc ; 1 1 1 1
breq MAP2 ; 1 1 2 2
cp rpws,rpwc ; 1 1
brcs MAP1 ; 1 2
nop ; 1
cbi PortB,bOut; 2
rjmp MAP3 ; 2
MAP1:
sbi PortB,bOut; 2
rjmp MAP3 ; 2
MAP2:
mov rpws,rpwn ; 1 1
ldi rpwc,cstep; 1 1
sbi PortB,bOut; 2 2
nop ; 1 1
nop ; 1 1
MAP3:
;-----------
;9999
;===========
.ENDM
;
; Beginn des Hauptprogrammes, initiere Variablen
;
Start:
ldi rpwc,cDflt ; Zaehler fuer den PWG
ldi rpws,cDflt ; Aktueller PWG-Wert
ldi rpwn,cDflt ; Naechster PWG-Wert
; Initiiere den Port B
;
ldi rmpr,pbmode ; Setze Datenrichtungsregister
out DDRB,rmpr ; von Port B
sbi PortB,bIn ; Schalte Pull-Up-Widerstand am Eingang an
; Starte Phase I : Warte bis der Eingang Null wird
;
; Schalte Fehler ein, bis das Signal korrekt ist
;
PH1:
macpwm ; 9
ldi rerr,cFbck; 1
ldi rpwn,cDflt; 1
lederron ; 2
delay3(3) ; 9
;
; Setze maximale Zeitdauer fuer die Erkennung eines Null-Signals
;
PH1a:
ldi ZL,Low(cCycl); 1
ldi ZH,HIGH(cCycl);1
; ---
; 24
; ===
; Warte bis der Eingang Null ist oder Zeitueberlauf eintritt
;
PH1b:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH2 ; 2
sbiw ZL,1 ; 2 2
breq PH1c ; 1 2
delay4(2) ; 8
rjmp PH1b ; 2
; ---
; 24
; ===
; Zeitueberlauf mit Eingang auf Eins
;
PH1c:
; (15)
delay4(1) ; 4
;
; Fehler bei aktivem Eingang, zaehle die Fehler
;
PH1d:
;(19 19)
dec rerr ; 1 1
brne PH1a ; 2 1
;
; Zu viele Fehler in Folge, setze Fehlerbedingung
;
delay1 ; 1
rjmp PH1 ; 2
; ---
; 24
; ===
; Starte Phase II: Eingang ist Null, warte auf aktives Signal
;
PH2:
; (12)
delay3(2) ; 6
delay2 ; 2
rjmp PH2b ; 2
;
; Fehler aufgetreten, setze Fehlerbedingung
;
PH2a:
macpwm ; 9
ldi rerr,cFbck; 1
ldi rpwn,cDflt; 1
lederron ; 2
delay3(3) ; 9
;
; Setze Zaehler fuer Zeitueberlauf bei inaktivem Eingang
;
PH2b:
; (22 22)
ldi ZL,LOW(cCycl); 1 1
ldi ZH,HIGH(cCycl); 1 1
; ------
; 24 24
; ======
; Warte bis der Eingang eins ist oder Zeitueberlauf passiert
;
PH2c:
macpwm ; 9 9 9 9
sbic PinB,bIn ; 2 2 2 1
rjmp PH3 ; 2
sbiw ZL,1 ; 2 2 2
breq PH2d ; 1 2 2
delay4(2) ; 8
rjmp PH2c ; 2
; ---
; 24
; ===
; Zeitueberlauf bei inaktivem Eingang, zaehle Fehler
;
PH2d:
; (15 15)
delay4(1) ; 4 4
PH2e:
; (19 19)
dec rtry ; 1 1
brne PH2b ; 1 2
nop ; 1
rjmp PH2a ; 2
; ---
; 24
; ===
; Phase III: Eingang ist aktiv geworden, warte cMin1 Schleifen, ob stabil
;
PH3:
; (12)
delay3(3) ; 9
delay2 ; 2
ldi rtry,cMin1; 1
; ---
; 24
; ===
; Warte bis cMin1 Schleifen mit aktivem Eingang abgelaufen
;
PH3a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH3b ; 2
dec rtry ; 1 1
breq PH4 ; 1 2
delay3(3) ; 9
rjmp PH3a ; 2
; ---
; 24
; ===
; Fruehes Inaktivierung des Einganges, Fehler bei Eingang Null
;
PH3b:
; (12)
delay3(1) ; 3
delay2 ; 2
rjmp PH2e ; 2
;
; Phase IV: Eingang ist Eins fuer cMin1 Schleifen, starte Toleranzzeit
;
PH4:
;(14)
delay4(2) ; 8
ldi rtry,cTlp ; 1
ldi rctr,cstep; 1
; ---
; 24
; ===
; Warte fuer Toleranzzeit oder auf inaktiven Eingang
;
PH4a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rtry ; 1 1
breq PH5 ; 1 2
delay3(3) ; 9
rjmp PH4a ; 2
; ---
; 24
; ===
;
; Phase V: Ende der Toleranzzeit, beginne Abwaertszaehlung
;
PH5:
; (14)
delay4(2) ; 8
delay2 ; 2
; ---
; 24
; ===
PH5a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rctr ; 1 1
breq PH6 ; 1 2
delay3(3) ; 9
rjmp PH5a ; 2
; ---
; 24
; ===
; Phase VI: Ende des Abwaertszaehlens, toleriere Nachlaufzeit
;
PH6:
; (14)
delay3(3) ; 9
ldi rtry,cTla ; 1
; ---
; 24
; ===
; Zeitueberlauf nach cTla Schleifen, beende bei Ueberlauf oder inaktiv
;
PH6a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rtry ; 1 1
breq PH6b ; 1 2
delay3(3) ; 9
rjmp PH6a ; 2
; ---
; 24
; ===
; Aktives Signal zu lang, Fehlerbedingung mit aktivem Eingang
;
PH6b:
; (14)
delay3(1) ; 3
rjmp PH1d ; 2
;
; Phase VII: Eingang inaktiv, pruefe auf ausreichende inaktive Zeit
;
;
PH7:
; (12)
delay4(2) ; 8
delay2 ; 2
ldi ZL,LOW(cMin0); 1
ldi ZH,HIGH(cMin0); 1
; ---
; 24
; ===
PH7a:
macpwm ; 9 9 9
sbic PinB,bIn ; 2 2 1
rjmp PH7b ; 2
sbiw ZL,1 ; 2 2
breq PH7c ; 1 2
delay4(2) ; 8
rjmp PH7a ; 2
; ---
; 24
; ===
; Fruehzeitiges Ende der Signalpause, Fehlerbedingung bei inaktivem Eingang
;
PH7b:
; (12)
delay3(1) ; 3
delay2 ; 2
rjmp PH1d ; 2
;
; Ende der Mindestdauer des inaktiven Signals, setze neuen Messwert
;
PH7c:
; (15)
mov rpwn,rctr ; 1
ldi rerr,cFbck; 1
lederroff ; 2
delay1 ; 1
rjmp PH2b ; 2
;
; Ende des Programmes
;

http://www.avr-asm-tutorial.net/avr_de/quellen/pcm2pwg4.asm1/20/2009 7:38:24 PM
http://www.avr-asm-tutorial.net/avr_gra/pcm2flow.gif

http://www.avr-asm-tutorial.net/avr_gra/pcm2flow.gif1/20/2009 7:38:27 PM
Program Flowchart PCM-to-Pulse-Width-Generator (C)2000 DG4FAC
Start

Init Pulse Width Set rErr, Default Set rErr, Default


Generator values Set ErrorLedOn Set ErrorLedOn

Init Port B Timeout-Counter Timeout-Counter Set rRtry to Set rRtry to cTlp Longtime-Counter
Set rRtry to cTla
I/O properties Z = cCycl Z = cCycl cMin1 Set rCtr to cStep Z = cMin0

PWG PWG PWG PWG PWG PWG PWG

=0 =1 =0 =0 =0 =0 =1
bIn bIn bIn bIn bIn bIn bIn

=1 =0 =1 =1 =1 =1 =0

>0 DEC >0 DEC >0 DEC >0 DEC >0 DEC >0 DEC >0 DEC
Z Z rRtry rRtry rCtr rRtry Z

=0 =0 =0 =0 =0 =0 =0

Set rpwn to rCtr


>0 DEC >0 DEC Set cErr to cFbck
rErr rErr Set ErrorLedOff

=0 =0

I II III IV V VI VII
1
bIn
0
Pulse Coded Modulation to
Pulse Width Generator
+
8
VCC LED
390
7
B2 +
5
B0 AT90S2323
+
Input PCM-coded signal

6
B1

Analog signal output


RES X1 X2 GND 100k
47k 1 2 3 4
XTAL
1µT +
1µT + 4 MHz

22 pK 22 pK

(C)2000 by DG4FAC
http://www.avr-asm-tutorial.net/avr_gra/pcm2pwg4.gif

http://www.avr-asm-tutorial.net/avr_gra/pcm2pwg4.gif1/20/2009 7:38:31 PM
Terminal kontrollierter Rechteckgenerator

Pfad: Home => AVR-Überblick => Anwendungen => Signal generator => Quellcode

Quellcode für den Pulsweiten-Generator


; *****************************************************************
; * Pulsweiten-Generator, programmierbar ueber die SIO 9k6 8N1 *
; * Eingabe der Pulslaenge und der aktiven Dauer in µs per *
; * Terminal. Ausgabe der Pulse an Port D, Bit 2 des STK 200 *
; * Geschrieben fuer das STK200 board und AT90S8515, anpassbar *
; * an AT90S2313 oder aehnliche Chips mit SIO *
; * (C)2000 by info!at!avr-asm-tutorial.net, Bugs sind willkommen *
; *****************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Used registers
;
.DEF rlpm=R0; Benutzt fuer LPM Befehle
.DEF rchar=R1; Zeichenpuffer SIO Kommunikation
.DEF rilo=R2; Low byte bei Zahleneingabe, Zaehler fuer aktiv high
.DEF rihi=R3; High byte bei Zahleneingabe, Zaehler fuer aktiv high
.DEF rjlo=R4; Low byte bei Multiplikation/inaktive phase
.DEF rjhi=R5; High byte bei Multiplikation/inactive phase
;
.DEF rmpr=R16; Vielzweckregister, byte/word
.DEF rcl=R18; Zykluszeit, word
.DEF rch=R19
.DEF ral=R20; Zeitraum fuer aktiv high, word
.DEF rah=R21
; X=R26/27: Zaehler fuer for Aktiv high
; Y=R28/29: Zaehler fuer inaktiv low
; Z=R30/31: Pointer fuer Lesen aus dem Programmspeicher
;
; Konstanten
;
.EQU OutPort=PortD; Ausgabeport fuer die Signale
.EQU DataDir=DDRD; Datenrichtungsregister des aktiven Ports
.EQU ActivePin=2; Gewuenschter Ausgabeanschluss
.EQU ModeControl=0b00000100; Mode Kontrollwort fuer Port
.EQU cDefCyc=25000; Default Wert fuer Zyklusdauer in us
.EQU cDefAct=2000; Default Wert fuer Aktiv High in us
.EQU fq=4000000; Quarzfrequenz auf dem Board in Hz
.EQU baud=9600; Baudrate fuer SIO Kommunikation
.EQU bddiv=(fq/(16*baud))-1; Baudratenteiler
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cbel=0x07; Bell character
;
; Makro Pruefe Eingabewert auf Default und kopiere in Register
;
.MACRO Default
MOV @0,rilo; Kopiere den Eingabewert in das Registerpaar
MOV @1,rihi
MOV rmpr,rilo; Teste ob input Null ist
OR rmpr,rihi
BRNE nodef; Nich Null, setze Default nicht
LDI @0,LOW(@2); Setze default Wert
LDI @1,HIGH(@2)
nodef:
.ENDM
;
; Code segment startet hier
;
.CSEG
;
; Reset- und Interrupt-Vektoren, werden hier nicht benutzt
;
RJMP Start; Reset vector
RETI; Ext Int 0
RETI; Ext Int 1
RETI; Timer 1 Capt
RETI; Timer 1 CompA
RETI; Timer 1 CompB
RETI; Timer 1 OVF
RETI; Timer 0 OVF
RETI; Serial Transfer Complete
RETI; UART Rx Complete
RETI; UART Data register empty
RETI; UART Tx Complete
RETI; Analog Comparator
;
; Subroutine fuer String aussenden
;
TxStr:
SBIS USR,UDRE; Warte bis Sendepuffer leer ist
RJMP TxStr
LPM; Lese naechsten Buchstaben aus Programmspeicher
AND rlpm,rlpm; NUL = Ende des Strings
BRNE txsend
RET
txsend:
LPM; Lese den Buchstaben noch einmal
OUT UDR,rlpm; Sende Buchstaben
ADIW ZL,1; Zeige auf naechstes Byte im Speicher
RJMP TxStr
;
; Subroutine fuer den Zahlenempfang (word, 0..65535)
;
RxWord:
CLR rilo; Leere Puffer
CLR rihi
rxw1:
SBIS USR,RXC; Teste ob Buchstabe empfangen
RJMP rxw1; Kein Buchstabe vorhanden, wiederhole
IN rmpr,UDR; Hole das Zeichen von der SIO
OUT UDR,rmpr; Echo zurueck an das Terminal
CPI rmpr,ccr; Return char = Ende der Eingabe
BREQ rxwx
SUBI rmpr,'0'; Subtrahiere 48
BRCS rxwerr; Keine Dezimalzahl, zurueck mit Carry gesetzt
CPI rmpr,10; Ziffer >9?
BRCS rxwok; keine Dezimalzahl
rxwerr:
LDI ZL,LOW(2*ErrorStr); Sende Error String
LDI ZH,HIGH(2*ErrorStr)
RCALL TxStr
SEC; Setze Carry, keine zulaessige Zahl
RET
rxwok:
MOV rjlo,rilo; Kopie des word fuer Multiplikaton
MOV rjhi,rihi
LSL rilo; Multipliziere mit 2 = 2*
ROL rihi
BRCS rxwerr; Ueberlauf, zurueck mit Carry
LSL rilo; Multipliziere noch mal mit 2, = 4*
ROL rihi
BRCS rxwerr; Ueberlauf
ADD rilo,rjlo; Addiere Kopie, = 5*
ADC rihi,rjhi
BRCS rxwerr; Ueberlauf
LSL rilo; Multipliziere mit 2, = 10*
ROL rihi
BRCS rxwerr; Ueberlauf
CLR rjhi; Addiere die Dezimalzahl
ADD rilo,rmpr
ADC rihi,rjhi
BRCS rxwerr; Ueberlauf
RJMP rxw1; Warte auf naechstes Zeichen
rxwx:
SBIS USR,UDRE; Warte bis Sendepuffer leer
RJMP rxwx
LDI rmpr,clf; Sende zusaetzlichen Zeilenvorschub
OUT UDR,rmpr
CLC; Clear carry, keine Fehler
RET
;
; Start des Programmes
;
Start:
;
; Benutze den Stack fuer Unterprogramme
;
LDI rmpr,HIGH(RAMEND); Stack auf hoechste RAM Adresse
OUT SPH,rmpr
LDI rmpr,LOW(RAMEND)
OUT SPL,rmpr
;
; Initiieren Port output
;
LDI rmpr,ModeControl; Setze output Modus
OUT DataDir,rmpr; an Datenrichtungsregister
;
; Initiiere SIO Kommunikation
;
LDI rmpr,bddiv; Setze Baudrate
OUT UBRR,rmpr
LDI rmpr,0b00011000; Enable von TX und RX
OUT UCR,rmpr
;
; Sende Hello Sequenz
;
hello:
LDI ZH,HIGH(2*InitStr); Point Z auf String
LDI ZL,LOW(2*InitStr)
RCALL TxStr
;
; Hole Wert fuer die Gesamtdauer
;
getcycle:
LDI ZH,HIGH(2*CycleStr); Point Z auf String
LDI ZL,LOW(2*CycleStr)
RCALL TxStr
RCALL RxWord
BRCS getcycle; Wiederhole, wenn Fehler
Default rcl,rch,cDefCyc
;
; Hole Wert fuer die aktive Dauer
;
getactive:
LDI ZH,HIGH(2*ActiveStr); Point Z auf String
LDI ZL,LOW(2*ActiveStr)
RCALL TxStr
RCALL RxWord
BRCS getactive; Wiederhole, wenn Fehler
Default ral,rah,cDefAct
;
; Berechne Zaehlerwert fuer die aktive Dauer
;
MOV XL,ral; Berechne aktive Zeit
MOV XH,rah
SBIW XL,5; mindestens 4 Zyklen
BRCS getcycle; ungueltige aktive Dauer
ADIW XL,1; Mindestens ein Zyklus erforderlich
MOV rilo,XL
MOV rihi,XH
;
; Berechne Dauer der inaktiven Zeit
;
MOV YL,rcl; Berechne inaktive Zeit
MOV YH,rch
SUB YL,XL; Subtrahiere Aktive Zeit
SBC YH,XH
BRCS getcycle; Aktive Zeit kuerzer als Gesamtzeit
SBIW YL,5; Subtrahiere Schleifenverzoegerung
BRCS getcycle; Weniger als drei Schleifendurchgaenge geht nicht
ADIW YL,1; minimum 1 loop
MOV rjlo,YL
MOV rjhi,YH
LDI ZH,HIGH(2*WaitStr); Gib ok-String aus
LDI ZL,LOW(2*WaitStr)
RCALL TxStr
;
; Zaehlen beginnt hier, pruefe ob Zeichen auf SIO
;
ctloop:
SBI OutPort,ActivePin; Starte aktive Phase
ActLoop:
SBIW XL,1; 0.5 µs
BRNE ActLoop; 0.5 µs
SBIC USR,RXC; Teste ob SIO RX leer
RJMP getcycle; Hole Eingabe von SIO
CBI Outport,ActivePin; Starte inaktive phase
InactLoop:
SBIW YL,1; 0.5 µs
BRNE InactLoop; 0.5 µs
MOV XL,rilo; Setze Zaehlerstand neu
MOV XH,rihi
MOV YL,rjlo
MOV YH,rjhi
NOP
NOP
RJMP ctloop; starte von vorne
;
; Text Strings fuer zum Senden, ANSI kodiert!
;
ErrorStr:
.DB cbel,ccr,clf,cesc,'[','3','3','m'
.DB "Fehler bei der Eingabe! "
.DB ccr,clf,cnul,cnul
ActiveStr:
.DB cesc,'[','3','2','m','*'
.DB "Gib inaktive Zeit ein (default = 2,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
CycleStr:
.DB cesc,'[','3','2','m','*'
.DB "Gib Zykluszeit ein (default = 25,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
WaitStr:
.DB cesc,'[','3','5','m','B'
.DB "etrieb auf dem Port."
.DB ccr,clf,cesc,'[','3','7','m','E'
.DB "ingabe einer neuen Zyklusdauer stoppt den Generator."
.DB ccr,clf,cnul,cnul
InitStr:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Setze
Screenfarben
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB ccr,clf,ccr,clf
.DB "Hallo Welt! "
.DB ccr,clf
.DB "Hier ist der Pulsweitengenerator bei der Arbeit!"
.DB ccr,clf
.DB "Alle Zeiten in Mikrosekunden, im Bereich 5..65535."
.DB ccr,clf
.DB "Neuer Wert unterbricht den Betrieb bis komplett eingegeben"
.DB ccr,clf,cnul,cnul
;
Check:
.DW check
;
; Ende des code segments
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/pwgsio2.html1/20/2009 7:38:37 PM
Terminal kontrollierter Rechteckgenerator

Pfad: Home => AVR-Überblick => Anwendungen => Signal generator

AVR-Einchip-Prozessor
AT90Sxxxx
von ATMEL in praktischen Beispielen.

ANSI-Terminal programmierbarer
Signalgenerator
Diese Anwendung stellt einen Rechteckgenerator für Signale von 5 bis 65.535 Mikrosekunden Dauer
und einstellbarer aktiver Dauer zur Verfügung. Die Angaben über die Dauer des Signals und die
aktive Dauer sind über ein ANSI-kompatibles Terminalprogramm über die serielle Schnittstelle des
STK200-Boards einstellbar.

Diese Anwendung erfordert:

● das STK200-Board mit einem AT90S8515 an Bord; oder alternativ: ein 2313 mit SIO
interface (Neueinstellung von Teilen des Quellcodes sind dann ebenfalls erforderlich!),
● ein Rechner mit einer freien COM-Schnittstelle und einem ANSI-kompatiblen
Terminalprogram (wie z.B. HyperTerminal für Windows),
● Kabelverbindung zwischen dem Rechner und dem STK200-Board über mindestens eine
Zweidrahtverbindung.

Anwendung:

1. Starte das Terminalprogram and stelle die notwendigen Parameter ein: Direktverbindung über
COM x, 9600 Baud, 8 Bit Daten, kein Paritätsbit, 1 Stop-Bit
2. Schalte das programmierte STK200-Board ein; das Terminal sollte auf schwarzen Hintergrund
wechseln und die Willkommen-Meldung ausgeben,
3. Gib die Dauer des Gesamtimpulses in Mikrosekunden ein (5 bis 65535) und schliesse mit der
Eingabetaste ab,
4. Gib die Dauer des aktiven Signals in Mikrosekunden ein (5 to 65534) und schliesse mit der
Eingabetaste ab,
5. Beobachte das Signal an Port D, Bit 2, des STK200-Boards!

Quellcode in HTML-Format Quellcode in asm-Format

Warnung:

● Das Ändern des Quellcodes im Bereich der Textausgabe am Ende (vom Label 'ErrorStr'
abwärts) kann wegen zweier ernster Compiler-Bugs ziemlich üble Folgen haben.
● Strings müssen immer eine gerade Anzahl von Zeichen haben!
● Die Anzahl an Byte oder Char Konstanten pro Zeile muss ebenfalls geradzahlig sein!
● Keine Strings und Konstanten auf einer Zeile mischen! Immer eine extra Zeile für beide
Sorten!
● Durchsuche nach dem Assemblieren das Listing nach der Meldung "Garbage at end of line!".
Dies ist kein fataler Fehler, also wird er nicht gemeldet und die Assemblierung abgebrochen!
Alle nachfolgenden Labels sind dann aber fehlerhaft.
● Vergleiche das Label 'Check' am Ende des Compiler-Listings. Wenn es exakt auf sich selbst
zeigt, ist alles mit den Strings in Ordnung. Zeigt es nicht auf sich selbst, dann ist ein Fehler in
den Strings und in den Labeln. Das Programm tut dann nicht das, was es soll.
● Die genannten Punkte sind durch einen Fehler des Compilers bei der Label-Adressierung
bedingt. Eine weitere, etwas seltenere Fehlerquelle, tritt bei der Verwendung von Semikolon
in Textstrings oder in Zeichenkonstanten auf. Fälschlicherweise fasst der Compiler dieses
Zeichen auch innerhalb von Strings oder Zeichenkonstanten als "Ende der Programmzeile" auf
und ignoriert den Rest der Zeile. Zur Umgehung des schwer zu findenden Fehlers das
Semikolon als Dezimal- oder Hex-Konstante auf einer Extrazeile, zusammen mit einem
weiteren Buchstaben oder Zeichen, unterbringen.
● Die goldene Regel der String-Programmierung: Strings IMMER hinter das Ende des
ausführbaren Codes platzieren. Bei Nichtbeachtung dieser Regel drohen verkehrte
Programmlabels und der AVR macht ziemlich interessante Dinge mit dem gefundenen
falschen Code.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/pwg.html1/20/2009 7:38:42 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/pwgsio2.asm

; **************************************************************
; * Pulsweiten-Generator, programmierbar ueber die SIO 9k6 8N1 *
; * Eingabe der Pulslaenge und der aktiven Dauer in µs per *
; * Terminal. Ausgabe der Pulse an Port D, Bit 2 des STK 200 *
; * Geschrieben fuer das STK200 board und AT90S8515, anpassbar *
; * an AT90S2313 oder aehnliche Chips mit SIO *
; * (C)2000 by info@avr-asm-tutorial.net, Bugs sind willkommen *
; **************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Used registers
;
.DEF rlpm=R0; Benutzt fuer LPM Befehle
.DEF rchar=R1; Zeichenpuffer SIO Kommunikation
.DEF rilo=R2; Low byte bei Zahleneingabe, Zaehler fuer aktiv high
.DEF rihi=R3; High byte bei Zahleneingabe, Zaehler fuer aktiv high
.DEF rjlo=R4; Low byte bei Multiplikation/inaktive phase
.DEF rjhi=R5; High byte bei Multiplikation/inactive phase
;
.DEF rmpr=R16; Vielzweckregister, byte/word
.DEF rcl=R18; Zykluszeit, word
.DEF rch=R19
.DEF ral=R20; Zeitraum fuer aktiv high, word
.DEF rah=R21
; X=R26/27: Zaehler fuer for Aktiv high
; Y=R28/29: Zaehler fuer inaktiv low
; Z=R30/31: Pointer fuer Lesen aus dem Programmspeicher
;
; Konstanten
;
.EQU OutPort=PortD; Ausgabeport fuer die Signale
.EQU DataDir=DDRD; Datenrichtungsregister des aktiven Ports
.EQU ActivePin=2; Gewuenschter Ausgabeanschluss
.EQU ModeControl=0b00000100; Mode Kontrollwort fuer Port
.EQU cDefCyc=25000; Default Wert fuer Zyklusdauer in us
.EQU cDefAct=2000; Default Wert fuer Aktiv High in us
.EQU fq=4000000; Quarzfrequenz auf dem Board in Hz
.EQU baud=9600; Baudrate fuer SIO Kommunikation
.EQU bddiv=(fq/(16*baud))-1; Baudratenteiler
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cbel=0x07; Bell character
;
; Makro Pruefe Eingabewert auf Default und kopiere in Register
;
.MACRO Default
mov @0,rilo; Kopiere den Eingabewert in das Registerpaar
mov @1,rihi
mov rmpr,rilo; Teste ob input Null ist
or rmpr,rihi
brne nodef; Nich Null, setze Default nicht
ldi @0,LOW(@2); Setze default Wert
ldi @1,HIGH(@2)
nodef:
.ENDM
;
; Code segment startet hier
;
.CSEG
;
; Reset- und Interrupt-Vektoren, werden hier nicht benutzt
;
rjmp Start; Reset vector
reti; Ext Int 0
reti; Ext Int 1
reti; Timer 1 Capt
reti; Timer 1 CompA
reti; Timer 1 CompB
reti; Timer 1 OVF
reti; Timer 0 OVF
reti; Serial Transfer Complete
reti; UART Rx Complete
reti; UART Data register empty
reti; UART Tx Complete
reti; Analog Comparator
;
; Subroutine fuer String aussenden
;
TxStr:
sbis USR,UDRE; Warte bis Sendepuffer leer ist
rjmp TxStr
lpm; Lese naechsten Buchstaben aus Programmspeicher
and rlpm,rlpm; NUL = Ende des Strings
brne txsend
ret
txsend:
lpm; Lese den Buchstaben noch einmal
out UDR,rlpm; Sende Buchstaben
adiw ZL,1; Zeige auf naechstes Byte im Speicher
rjmp TxStr
;
; Subroutine fuer den Zahlenempfang (word, 0..65535)
;
RxWord:
clr rilo; Leere Puffer
clr rihi
rxw1:
sbis USR,RXC; Teste ob Buchstabe empfangen
rjmp rxw1; Kein Buchstabe vorhanden, wiederhole
in rmpr,UDR; Hole das Zeichen von der SIO
out UDR,rmpr; Echo zurueck an das Terminal
cpi rmpr,ccr; Return char = Ende der Eingabe
breq rxwx
subi rmpr,'0'; Subtrahiere 48
brcs rxwerr; Keine Dezimalzahl, zurueck mit Carry gesetzt
cpi rmpr,10; Ziffer >9?
brcs rxwok; keine Dezimalzahl
rxwerr:
ldi ZL,LOW(2*ErrorStr); Sende Error String
ldi ZH,HIGH(2*ErrorStr)
rcall TxStr
sec; Setze Carry, keine zulaessige Zahl
ret
rxwok:
mov rjlo,rilo; Kopie des word fuer Multiplikaton
mov rjhi,rihi
lsl rilo; Multipliziere mit 2 = 2*
rol rihi
brcs rxwerr; Ueberlauf, zurueck mit Carry
lsl rilo; Multipliziere noch mal mit 2, = 4*
rol rihi
brcs rxwerr; Ueberlauf
add rilo,rjlo; Addiere Kopie, = 5*
adc rihi,rjhi
brcs rxwerr; Ueberlauf
lsl rilo; Multipliziere mit 2, = 10*
rol rihi
brcs rxwerr; Ueberlauf
clr rjhi; Addiere die Dezimalzahl
add rilo,rmpr
adc rihi,rjhi
brcs rxwerr; Ueberlauf
rjmp rxw1; Warte auf naechstes Zeichen
rxwx:
sbis USR,UDRE; Warte bis Sendepuffer leer
rjmp rxwx
ldi rmpr,clf; Sende zusaetzlichen Zeilenvorschub
out UDR,rmpr
clc; Clear carry, keine Fehler
ret
;
; Start des Programmes
;
Start:
;
; Benutze den Stack fuer Unterprogramme
;
ldi rmpr,HIGH(RAMEND); Stack auf hoechste RAM Adresse
out SPH,rmpr
ldi rmpr,LOW(RAMEND)
out SPL,rmpr
;
; Initiieren Port output
;
ldi rmpr,ModeControl; Setze output Modus
out DataDir,rmpr; an Datenrichtungsregister
;
; Initiiere SIO Kommunikation
;
ldi rmpr,bddiv; Setze Baudrate
out UBRR,rmpr
ldi rmpr,0b00011000; Enable von TX und RX
out UCR,rmpr
;
; Sende Hello Sequenz
;
hello:
ldi ZH,HIGH(2*InitStr); Point Z auf String
ldi ZL,LOW(2*InitStr)
rcall TxStr
;
; Hole Wert fuer die Gesamtdauer
;
getcycle:
ldi ZH,HIGH(2*CycleStr); Point Z auf String
ldi ZL,LOW(2*CycleStr)
rcall TxStr
rcall RxWord
brcs getcycle; Wiederhole, wenn Fehler
default rcl,rch,cDefCyc
;
; Hole Wert fuer die aktive Dauer
;
getactive:
ldi ZH,HIGH(2*ActiveStr); Point Z auf String
ldi ZL,LOW(2*ActiveStr)
rcall TxStr
rcall RxWord
brcs getactive; Wiederhole, wenn Fehler
default ral,rah,cDefAct
;
; Berechne Zaehlerwert fuer die aktive Dauer
;
mov XL,ral; Berechne aktive Zeit
mov XH,rah
sbiw XL,5; mindestens 4 Zyklen
brcs getcycle; ungueltige aktive Dauer
adiw XL,1; Mindestens ein Zyklus erforderlich
mov rilo,XL
mov rihi,XH
;
; Berechne Dauer der inaktiven Zeit
;
mov YL,rcl; Berechne inaktive Zeit
mov YH,rch
sub YL,XL; Subtrahiere Aktive Zeit
sbc YH,XH
brcs getcycle; Aktive Zeit kuerzer als Gesamtzeit
sbiw YL,5; Subtrahiere Schleifenverzoegerung
brcs getcycle; Weniger als drei Schleifendurchgaenge geht nicht
adiw YL,1; minimum 1 loop
mov rjlo,YL
mov rjhi,YH
ldi ZH,HIGH(2*WaitStr); Gib ok-String aus
ldi ZL,LOW(2*WaitStr)
rcall TxStr
;
; Zaehlen beginnt hier, pruefe ob Zeichen auf SIO
;
ctloop:
sbi OutPort,ActivePin; Starte aktive Phase
ActLoop:
sbiw XL,1; 0.5 µs
brne ActLoop; 0.5 µs
sbic USR,RXC; Teste ob SIO RX leer
rjmp getcycle; Hole Eingabe von SIO
cbi Outport,ActivePin; Starte inaktive phase
InactLoop:
sbiw YL,1; 0.5 µs
brne InactLoop; 0.5 µs
mov XL,rilo; Setze Zaehlerstand neu
mov XH,rihi
mov YL,rjlo
mov YH,rjhi
nop
nop
rjmp ctloop; starte von vorne
;
; Text Strings fuer zum Senden, ANSI kodiert!
;
ErrorStr:
.DB cbel,ccr,clf,cesc,'[','3','3','m'
.DB "Fehler bei der Eingabe! "
.DB ccr,clf,cnul,cnul
ActiveStr:
.DB cesc,'[','3','2','m','*'
.DB "Gib inaktive Zeit ein (default = 2,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
CycleStr:
.DB cesc,'[','3','2','m','*'
.DB "Gib Zykluszeit ein (default = 25,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
WaitStr:
.DB cesc,'[','3','5','m','B'
.DB "etrieb auf dem Port."
.DB ccr,clf,cesc,'[','3','7','m','E'
.DB "ingabe einer neuen Zyklusdauer stoppt den Generator."
.DB ccr,clf,cnul,cnul
InitStr:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Setze Screenfarben
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB ccr,clf,ccr,clf
.DB "Hallo Welt! "
.DB ccr,clf
.DB "Hier ist der Pulsweitengenerator bei der Arbeit!"
.DB ccr,clf
.DB "Alle Zeiten in Mikrosekunden, im Bereich 5..65535."
.DB ccr,clf
.DB "Neuer Wert unterbricht den Betrieb bis komplett eingegeben"
.DB ccr,clf,cnul,cnul
;
Check:
.DW check
;
; Ende des code segments
;

http://www.avr-asm-tutorial.net/avr_de/quellen/pwgsio2.asm1/20/2009 7:38:45 PM
Rechteckgenerator ATmega8 - Quellcode Hauptprogramm

Pfad: Home => AVR-Übersicht => Anwendungen => Rechteckgenerator = > Quellcode
Hauptprogramm

Rechteckgenerator mit
ATmega8 - Quellcode
Hauptprogramm

;
; ***************************************************
; * Einstellbarer Rechteckgenerator mit ATmega8 *
; * Frequenz (0.25Hz..8MHz) und PulsWeite (0.00.. *
; * 100.00%) variabel, LCD-Anzeige (waehlbar: ein- *
; * zeilige/mehrzeilige Anzeige, 16..40 Zeichen pro *
; * Zeile), zeigt Frequenz oder Umdrehungsgeschwin- *
; * digkeit sowie Pulsweite in % an *
; * Benoetigt die Dateien "rectgen_m8_table.inc" *
; * und "Lcd8_02WO_rec.inc" *
; * Version 1 vom 21. April 2006 *
; * (C)2006 by info!at!avr-asm-tutorial.net *
; ***************************************************
;
.NOLIST
.INCLUDE "m8def.inc"
.LIST
;
; Debug Informationen
;
.EQU dbgOn = 0 ; Debug ein oder aus
.IF dbgOn
.EQU cAdc0 = 1000 ; ADC0-Wert
.EQU cAdc1 = 511 ; ADC1-Wert
.EQU cFlg = 0
;.EQU cFlg = (1<<bTime)
;.EQU cFlg = (1<<bRpm)
;.EQU cFlg = (1<<bPw)
.ENDIF
.EQU dbghx = 0 ; Debug Hex-Ausgabe auf LCD
;
; Hardware
; ___________
; __ 10k/ | _
;+5V O-|__|--|RESET PC5|--O--O O--| Pulseweite anzeigen
; | | _ (nur einzeilige LCD!)
; LCD D0 O--|PD0 PC4|--O--O O--| Signale invertieren
; | | _
; LCD D1 O--|PD1 PC3|--O--O O--| UPM anzeigen
; | | _
; LCD D2 O--|PD2 PC2|--O--O O--| Zeit anzeigen
; | |
; LCD D3 O--|PD3 ADC1|--O 0..5V Pulsweiteneinstellung
; | A T |
; LCD D4 O--|PD4 ADC0|--O 0..5V Frequenzeinstellung
; | mega |
; +5V O--|VCC GND|--O GND
; | 8 | 10nF
; GND O--|GND AREF|--O--||--| AREF
; | | ___ 22H/10nF
; XTAL1 O--|XTAL1 AVCC|--O--|___|--O +5V
; | |
; XTAL2 O--|XTAL2 PB5SCK|--O LCD R/W, SCK
; | |
; LCD D5 O--|PD5 PB4MISO|--O LCD RS, MISO
; | |
; LCD D6 O--|PD6 PB3MOSI|--O MOSI
; | |
; LCD D7 O--|PD7 PB2OC1B|--O Ausgang B
; | |
; LCD E O--|PB0 PB1OC1A|--O Ausgang A
; |____________|
;
;
; Timing
; ------
;
; TC0: Vorteiler = 1024, Ueberlauf Interrupt, @16MHz:
; 16.384 ms, abwaertszaehler von 30 auf 0, bei 0:
; (491.52 ms) startet ADC-Wandlerzyklus
;
; ADC-Kanaele 1 und 2: Wandlung gestartet mit TC0,
; ADC-Teiler = 128, @16MHz, erster ADC-Complete
; Interrupt nach 200 us, zweiter Interrupt nach
; 104 us, ADC wird abgeschaltet und Komplett-Flagge
; gesetzt nach zwei vollstaendigen Wandlungen
;
; ADC-Komplett-Flagge: liest Wert fuer die Einstellung
; des TC1-CTC (ICR1-CTC) aus Tabelleneintrag von
; ADC0, berechnet COMPA/COMPB-Wert aus dem CTC-Wert
; und ADC1, setzt TC1-ICR1 und COMPA/COMPB-Werte,
; TC1-Vorteiler und TC1-Ausgangspoaritaet
;
; TC1: Schneller PWM mode/WGM=14, Vorteiler = 1..1024 (ab-
; haengig von gewaehlter Frequenz), ICR1 bestimmt den
; TOP-Wert, COMPA/B bestimmt phasenmodulierte Umkehr
; des Ausgangssignals
;
; **************************************************
; D E F I N I T I O N E N
; **************************************************
;
; Konstanten
;
.EQU clock = 16000000 ; Taktfrequenz
.EQU cDivF5 = $00 ; = clock * 100 (5 Bytes)
.EQU cDivF4 = $5F
.EQU cDivF3 = $5E
.EQU cDivF2 = $10
.EQU cDivF1 = $00
.EQU cDivU5 = $16 ; = clock * 100 * 60 (5 Bytes)
.EQU cDivU4 = $5A
.EQU cDivU3 = $0B
.EQU cDivU2 = $C0
.EQU cDivU1 = $00
.EQU cLcdLw = 24 ; Anzahl Zeichen pro Zeile der LCD
.EQU cLcdLn = 2 ; Anzahl Zeilen der LCD
;.EQU cLcdMicro = $E4 ; Mikro-Zeichen der LCD, nicht ok bei L2432
.EQU cLcdMicro = 'u' ; anstelle des Mikro-Zeichens
.EQU cEn = 0 ; Englische oder deutsche Version
;
; Abhaengige Konstanten
;
.EQU cTMult = (256000000/clock)*100
.IF cEn
.EQU c1000s = $2C ; Komma
.EQU cDecs = $2E ; Punkt
.ELSE
.EQU c1000s = $2E ; Punkt
.EQU cDecs = $2C ; Komma
.ENDIF
;
; Register
;
; benutzt: R0..R13 fuer Berechnungen
; frei: R14
.DEF rSreg = R15 ; Status-Sicherungs-Register
.DEF rmp = R16 ; Multipurpose Register ausserhalb Ints
.DEF rimp = R17 ; Multipurpose Register innerhalb Ints
.DEF rFlg = R18 ; Flaggenregister
.EQU bTime = 0 ; Zeit anstelle Frequenz anzeigen
.EQU bRpm = 1 ; UPM anstelle Frequenz anzeigen
.EQU bInv = 2 ; Invertieren des Ausgangssignals
.EQU bAdc0 = 3 ; ADC-Kanal 0 Komplett-Flagge
.EQU bAdc1 = 4 ; ADC-Kanal 1 Komplett-Flagge
.IF cLcdLn==1
.EQU bPw = 7 ; Anzeige Pulsweite auf Zeile 1
(einzeilige LCD)
.ENDIF
.DEF rAdc0L = R19 ; LSB letztes ADC0-Ergebnis
.DEF rAdc0H = R20 ; dto., MSB
.DEF rAdc1L = R21 ; LSB letztes ADC1-Ergebnis
.DEF rAdc1H = R22 ; dto., MSB
.DEF rAdcC = R23 ; Zaehler fuer verzoegerten ADC Startzyklus
; frei: R24..R25
; benutzt: X (R27:R26) fuer Berechnungen
; frei: Y (R29:R28)
; benutzt: Z (R31:R30) fuer Berechnungen
;
; Ports
;
; LCD-Port-Anschluesse
.EQU pLcdData = PORTD
.EQU pLcdCtrl = PORTB
.EQU pbLcdE = 0
.EQU pbLcdRs = 4
.EQU pbLcdRw = 5
; Schalter Port-Anschluesse
.EQU pSwtchOut = PORTC
.EQU pSwtchIn = PINC
.EQU pbTime = 2
.EQU pbRpm = 3
.EQU pbInv = 4
.EQU pbPwm = 5
; Signalausgaenge
.EQU pSignOut = PORTB
.EQU pSignDdr = DDRB
.EQU pbSignA = 1
.EQU pbSignB = 2
;
; SRAM Positionen
;
.DSEG
.ORG $0060
sCtc: ; CTC-Teiler fuer TC1
.BYTE 2
sCmp: ; COMPA/B Pulsweite TC1
.BYTE 2
sPre: ; Vorteiler TC1
.BYTE 1
sMode: ; Modus TC1
.BYTE 1
sLcdL1: ; Zeile 1 der LCD
.BYTE cLcdLw
.IF cLcdLn>1
sLcdL2: ; Zeile 2 der LCD
.BYTE cLcdLw
.ENDIF
;
; **************************************************
; R E S E T - und I N T - V E C T O R E N
; **************************************************
;
; Code-Segment
.CSEG
.ORG $0000
;
rjmp main ; Reset Vektor, Sprung zum Beginn
reti ; INT0, nicht verwendet
reti ; INT1, nicht verwendet
reti ; TIMER2COMP, nicht verwendet
reti ; TIMER2OVF, nicht verwendet
reti ; TIMER1CAPT, nicht verwendet
reti ; TIMER1COMPA, nicht verwendet
reti ; TIMER1COMPB, nicht verwendet
reti ; TIMER1OVF, nicht verwendet
rjmp TC0OvflwInt ; TIMER0OVF
reti ; SPI, STC, nicht verwendet
reti ; USART, RXC, nicht verwendet
reti ; USART, UDRE, nicht verwendet
reti ; USART, TXC, nicht verwendet
rjmp AdcInt ; ADC
reti ; EE_RDY, nicht verwendet
reti ; ANA_COMP, nicht verwendet
reti ; TWI, nicht verwendet
reti ; SPM_RDY, nicht verwendet
;
; **************************************************
; I N T - V E K T O R - R O U T I N E N
; **************************************************
;
; TC0 Ueberlauf Interrupt, startet ADC-Messzyklus
;
TC0OvflwInt:
in rSreg,SREG ; sichere Status
dec rAdcC ; zaehle Verzoegerungszaehler abwaerts
brne TC0OvflwInt1
ldi rAdcC,30 ; Neustart Zaehler
ldi rimp,(1<<REFS0) ; ADMUX auf Kanal 0
out ADMUX,rimp
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; starte Umwandlung Kanal 0
cbr rFlg,1<<bAdc0 ; setze Kanal-0-Komplett-Flagge
TC0OvflwInt1:
out SREG,rSreg ; Status wieder herstellen
reti
;
; ADC-Fertig-Interrupt, lese ADC-Wert
;
AdcInt:
in rSreg,SREG ; sichere Status
sbrc rFlg,bAdc0 ; Kanal 0 fertig?
rjmp AdcInt1 ; ja, starte naechsten Kanal
in rAdc0L,ADCL ; lese Kanal 0
in rAdc0H,ADCH
ldi rimp,(1<<REFS0)|(1<<MUX0) ; setze Kanal 1
out ADMUX,rimp
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; starte Umwandlung Kanal 1
sbr rFlg,1<<bAdc0 ; setze Kanal-0-Komplettflagge
out SREG,rSreg ; stelle Status wieder her
reti
AdcInt1:
in rAdc1L,ADCL ; lese Kanal 1
in rAdc1H,ADCH
ldi rimp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; ADC ausschalten
out ADCSRA,rimp
sbr rFlg,1<<bAdc1 ; setze Kanal-1-Komplettflagge
out SREG,rSreg ; stelle Status wieder her
reti
;
; **************************************************
; S U B R O U T I N E N
; **************************************************
;
; Lese aktuellen CTC- und Vorteiler-Wert und berechnet
; die Rate in R7:R6:R5:R4
;
GetRate:
lds rmp,sPre ; lese Vorteiler nach rmp
andi rmp,(1<<CS12)|(1<<CS11)|(1<<CS10)
breq GetRate2 ; Vorteiler ist Null, setze Carry
lds R4,sCtc ; lese Teiler nach R7:R6:R5:R4
lds R5,sCtc+1
clr R6
clr R7
dec rmp
breq GetRate1 ; Vorteiler = 1
lsl R4 ; Teiler * 2
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 4
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 8
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; Teiler = 8
lsl R4 ; Teiler * 16
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 32
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 64
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; Vorteiler = 64
lsl R4 ; Teiler * 128
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 256
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; Vorteiler = 256
lsl R4 ; Teiler * 512
rol R5
rol R6
rol R7
lsl R4 ; Teiler * 1024
rol R5
rol R6
rol R7
GetRate1: ; Timer ist aktiv, loesche carry
clc
ret
GetRate2: ; Timer ist inaktiv, setze carry
sec
ret
;
; Berechne Anzeigentext aus aktuellen Timer-Parametern
;
Calc:
sbrc rFlg,bTime ; Zeit anzeigen?
rjmp CalcTime ; ja, berechne Zeit
clr R8 ; loesche Divisionsergebnis in R11:R10:R9:R8
inc R8 ; setze letztes Bit als Zaehler
clr R9
clr R10
clr R11
rcall GetRate
brcs L1Lcd ; Timer ist aus, Frequenz = 0
clr R3 ; setze Teiler in R3:R2:R1:R0:ZH:ZL:XH:XL
clr R2
clr R1
sbrc rFlg,bRpm ; UPM anzeigen?
rjmp Calc1 ; ja
ldi rmp,cDivF5 ; Frequenz anzeigen
mov R0,rmp
ldi ZH,cDivF4
ldi ZL,cDivF3
ldi XH,cDivF2
ldi XL,cDivF1
rjmp Calc2
Calc1:
ldi rmp,cDivU5 ; zeige UPM an
mov R0,rmp
ldi ZH,cDivU4
ldi ZL,cDivU3
ldi XH,cDivU2
ldi XL,cDivU1
Calc2:
lsl XL ; * 2
rol XH
rol ZL
rol ZH
rol R0
rol R1
rol R2
rol R3
cp R0,R4 ; vergleichen
cpc R1,R5
cpc R2,R6
cpc R3,R7
brcs Calc3
sub R0,R4 ; subtrahieren
sbc R1,R5
sbc R2,R6
sbc R3,R7
sec
rjmp Calc4
Calc3:
clc
Calc4:
rol R8 ; rolle Ergebnisbit ein
rol R9
rol R10
rol R11
brcc Calc2 ; wiederhole 32 mal
lsl ZH ; aufrunden?
rol R0
rol R1
rol R2
rol R3
cp R0,R4
cpc R1,R5
cpc R2,R6
cpc R3,R7
brcs Calc5
ldi rmp,1
add R8,rmp
ldi rmp,0
adc R9,rmp
adc R10,rmp
adc R11,rmp
Calc5:
;
; Ergebnis in R11:R10:R9:R8 auf Zeile 1
;
L1Lcd:
clr R0 ; R0 ist Flagge fuer fuehrende Nullen
ldi ZH,HIGH(2*DecTab32) ; Zeiger auf Dezimaltabelle
ldi ZL,LOW(2*DecTab32)
ldi XH,HIGH(sLcdL1) ; X zeigt auf LCD-Zeile
ldi XL,LOW(sLcdL1)
ldi rmp,'F' ; zeige Frequenz an
sbrc rFlg,bRpm
ldi rmp,'R' ; zeige UPM an
sbrc rFlg,bTime
ldi rmp,'T' ; zeige Zeit an
st X+,rmp ; setze erstes Zeichen
.IF cLcdLw>16
ldi rmp,' ' ; fuege ein Leerzeichen zu
st X+,rmp
ldi rmp,'=' ; fuege = zu
st X+,rmp
rcall Dec32 ; schreibe 100 Millionen-Stelle
.ELSE
rcall Dec32 ; schreibe 10 Millionen-Stelle
ld rmp,-X ; lese letzte Zeichenposition
cpi rmp,' ' ; Leerzeichen?
brne L1Lcd00
ldi rmp,'=' ; fuege = an
st X,rmp
L1Lcd00:
adiw XL,1
.ENDIF
rcall Dec32 ; schreibe Millionen
ldi rmp,c1000s
tst R0
brne L1Lcd0a
ldi rmp,' '
L1Lcd0a:
st X+,rmp
rcall Dec32 ; schreibe 100,000'er
rcall Dec32 ; schreibe 10,000'er
rcall Dec32 ; schreibe 1,000'er
ldi rmp,c1000s
tst R0
brne L1Lcd0b
ldi rmp,' '
L1Lcd0b:
st X+,rmp
rcall Dec32 ; schreibe 100'er
rcall Dec32 ; schreibe 10'er
inc R0 ; schreibe fuehrende Nullen
rcall Dec32 ; schreibe 1'er
tst R8 ; zeige Nachkommastellen an?
breq L1Lcd1
ldi rmp,cDecs ; setze Dezimalzeichen
st X+,rmp
rcall Dec32 ; schreibe 0.1'er
ldi rmp,'0'
add rmp,R8 ; schreibe 0.01'er
st X+,rmp
rjmp L1Lcd2
L1Lcd1:
ldi rmp,' ' ; leere Dezimalstellen
st X+,rmp
st X+,rmp
st X+,rmp
L1Lcd2:
.IF cLcdLw>16
ldi rmp,' ' ; fuege Leerzeichen hinzu
st X+,rmp
.ENDIF
sbrc rFlg,bTime ; Zeit anzeigen?
rjmp L1Lcd4 ; ja
sbrc rFlg,bRpm ; UPM anzeigen?
rjmp L1Lcd3 ; ja
ldi rmp,'H' ; Frequenz anzeigen
st X+,rmp
ldi rmp,'z'
st X+,rmp
rjmp L1Lcd5
L1Lcd3:
ldi rmp,'p' ; zeige Upm an
st X+,rmp
ldi rmp,'m'
st X+,rmp
rjmp L1Lcd5
L1Lcd4:
ldi rmp,cLcdMicro
st X+,rmp
ldi rmp,'s'
st X+,rmp
L1Lcd5:
.IF cLcdLw>16
ldi rmp,' '
mov R0,rmp
ldi rmp,cLcdLw-19
L1Lcd6:
st X+,R0
dec rmp
brne L1Lcd6
.ENDIF
ret
;
; Berechne naechste Dezimalstelle einer 32-Bit-Zahl
;
Dec32:
lpm R4,Z+ ; lese naechste Dezimalzahl
lpm R5,Z+
lpm R6,Z+
lpm R7,Z+
clr rmp
Dec32a:
cp R8,R4 ; vergleiche die Zahl mit der Dezimalzahl
cpc R9,R5
cpc R10,R6
cpc R11,R7
brcs Dec32b
sub R8,R4
sbc R9,R5
sbc R10,R6
sbc R11,R7
inc rmp ; erhoehe Ergebnis
rjmp Dec32a ; wiederhole
Dec32b:
add R0,rmp ; addiere zur fuehrenden Nullen-Flagge
subi rmp,-'0' ; addiere ASCII Null
tst R0 ; fuehrende Null?
brne Dec32c
ldi rmp,' ' ; setze fuehrende Null
Dec32c:
st X+,rmp ; speichere Zeichen im SRAM
ret
;
; 32 Bit Dezimaltabelle fuer Zahlumwandlung
;
DecTab32:
.DB $00,$CA,$9A,$3B ; 1000 mio
.DB $00,$E1,$F5,$05 ; 100 mio
.DB $80,$96,$98,$00 ; 10 mio
.DB $40,$42,$0F,$00 ; 1 mio
.DB $A0,$86,$01,$00 ; 100,000
DecTab16:
.DB $10,$27,$00,$00 ; 10,000
.DB $E8,$03,$00,$00 ; 1,000
.DB $64,$00,$00,$00 ; 100
.DB $0A,$00,$00,$00 ; 10
;
; Berechne und zeige Zeit an
;
CalcTime:
rcall GetRate ; Lese Rate nach R7:R6:R5:R4
brcc CalcTime1 ; Timer ist aktiv, berechne Zeit
rjmp L1Lcd ; Timer ist inaktiv, zeige 0 an
CalcTime1:
mov R2,R4 ; kopiere Multiplikator nach R7:R:R5:R4:R3:R2
mov R3,R5
mov R4,R6
mov R5,R7
clr R6
clr R7
clr R8 ; loesche Ergebnis in R13:R12:R11:R10:R9:R8
clr R9
clr R10
clr R11
clr R12
clr R13
ldi rmp,HIGH(cTMult) ; lade Multiplikator in R1:R0
mov R1,rmp
ldi rmp,LOW(cTMult)
mov R0,rmp
CalcTime2:
lsr R1 ; schiebe naechstes Bit des Multiplikators in Carry
ror R0
brcc CalcTime3
add R8,R2 ; addiere den Multiplikator
adc R9,R3
adc R10,R4
adc R11,R5
adc R12,R6
adc R13,R7
CalcTime3:
lsl R2 ; Multipliziere Multiplikator mit 2
rol R3
rol R4
rol R5
rol R6
rol R7
tst R0 ; pruefe LSB auf Ende der Multiplikation
brne CalcTime2
tst R1 ; pruefe MSB auf Ende der Multiplikation
brne CalcTime2
mov rmp,R8 ; niedrigstes Byte fuer Runden
mov R8,R9 ; schiebe Ergebnis rechts = dividiere mit 256
mov R9,R10
mov R10,R11
mov R11,R12
tst R13 ; pruefe auf Ueberlauf
breq CalcTime5
CalcTime4:
ldi rmp,0xFF ; Ueberlauf, setze auf groesste Zahl
mov R8,rmp
mov R9,rmp
mov R10,rmp
mov R11,rmp
rjmp L1Lcd ; und zeige an
CalcTime5:
cpi rmp,0x80
brcs CalcTime6
ldi rmp,0x01 ; runde auf
add R8,rmp
ldi rmp,0x00
adc R9,rmp
adc R10,rmp
adc R11,rmp
brcs CalcTime4
CalcTime6:
rjmp L1Lcd
;
; Berechne Pulsweite, zuerst Pulsdauer mit 10000 multiplizieren,
; dann das Ergebnis durch die gesamte Pulsdauer dividieren
;
CalcPw:
lds R7,sCmp ; Lese aktive Pulsdauer nach R10:R9:R8:R7
lds R8,sCmp+1
clr R9
clr R10
clr R0 ; loesche Multiplikationsergebnis in R6:R5:R4:R2:R1:
R0
clr R1
clr R2
clr R3
clr R4
clr R5
clr R6
ldi rmp,HIGH(10000) ; setze R12:R11 auf 10000
mov R12,rmp
ldi rmp,LOW(10000)
mov R11,rmp
CalcPw1:
lsr R12 ; schiebe naechstes Bit rechts in Carry
ror R11
brcc CalcPw2 ; Null herausgeschoben
add R0,R7 ; addiere den Multiplikator
adc R1,R8
adc R2,R9
adc R3,R10
CalcPw2:
lsl R7 ; multipliziere mit 2
rol R8
rol R9
rol R10
tst R11 ; pruefe Ende der Multiplikation
brne CalcPw1 ; weitermachen
tst R12
brne CalcPw1 ; weitermachen
lds R7,sCtc ; lese CTC-Wert nach R9:R8:R7
lds R8,sCtc+1
clr R9
clr R10 ; loesche Divisionsergebnis
inc R10
clr R11
clr R12
clr R13
CalcPw3:
lsl R0 ; schiebe links
rol R1
rol R2
rol R3
rol R4
rol R5
rol R6
cp R4,R7 ; vergleiche mit Teiler
cpc R5,R8
cpc R6,R9
brcs CalcPw4 ; nicht sutrahieren
sub R4,R7
sbc R5,R8
sbc R6,R9
sec
rjmp CalcPw5 ; schiebe eine 1 hinein
CalcPw4:
clc ; schiebe eine 0 hinein
CalcPw5:
rol R10 ; schiebe in Ergebnis hinein
rol R11
rol R12
rol R13
brcc CalcPw3
lsl R3 ; runde Ergebnis
rol R4
rol R5
rol R6
cp R4,R7
cpc R5,R8
cpc R6,R9
brcs L2Lcd
ldi rmp,1
add R10,rmp
ldi rmp,0
adc R11,rmp
adc R12,rmp
adc R13,rmp
L2Lcd:
mov R8,R10
mov R9,R11
mov R10,R12
mov R11,R13
ldi ZH,HIGH(2*DecTab16)
ldi ZL,LOW(2*DecTab16)
clr R0
.IF cLcdLn==1
ldi XH,HIGH(sLcdL1)
ldi XL,LOW(sLcdL1)
.ELSE
ldi XH,HIGH(sLcdL2)
ldi XL,LOW(sLcdL2)
.ENDIF
ldi rmp,'P'
st X+,rmp
ldi rmp,' '
st X+,rmp
ldi rmp,'='
st X+,rmp
rcall Dec32 ; schreibe 100'er
rcall Dec32 ; schreibe 10'er
inc R0
rcall Dec32 ; schreibe 1'er
ldi rmp,cDecs ; schreibe Dezimaltrenner
st X+,rmp
rcall Dec32 ; schreibe 0.1'er
ldi rmp,'0' ; schreibe 0.01'er
add rmp,R8
st X+,rmp
ldi rmp,'%'
st X+,rmp
ldi rmp,' '
mov R0,rmp
ldi rmp,cLcdLw-9
L2Lcd1:
st X+,R0
dec rmp
brne L2Lcd1
ret
;
; **************************************************
; E R N E U E R E T I M E R W E R T E
; **************************************************
;
; Wandle ADC-Werte um und setze Timer
;
Convert:
ldi ZH,HIGH(2*Datatable)
ldi ZL,LOW(2*Datatable)
add ZL,rAdc0L ; addiere ADC0-Wert
adc ZH,rAdc0H
add ZL,rAdc0L ; addiere ADC0-Wert erneut
adc ZH,rAdc0H
lpm R0,Z+ ; lese Tabellenwert
lpm R1,Z
sts sCtc,R0 ; kopiere ins SRAM
sts sCtc+1,R1
clr R2 ; loesche Ergebnis fuer Multiplikation in R3:R2:R1:R0
clr R3
mov R4,rAdc1L ; kopiere ADC1-Wert nach R5:R4
mov R5,rAdc1H
clr R9 ; loesche Ergebnis in R9:R8:R7:R6
clr R8
clr R7
clr R6
Convert1:
lsr R5 ; schiebe niedrigstes Bit in Carry
ror R4
brcc Convert2 ; Bit ist Null, addiere nicht
add R6,R0
adc R7,R1
adc R8,R2
adc R9,R3
Convert2:
lsl R0 ; schiebe Muliplikator eins links
rol R1
rol R2
rol R3
tst R4 ; teste ob Multiplikator Nul ist
brne Convert1
tst R5
brne Convert1
lsr R9 ; dividiere Ergebnis durch 2
ror R8
ror R7
lsr R9 ; dividiere Ergebnis durch 4
ror R8
ror R7
brcc Convert3
ldi rmp,1 ; runde auf
add R7,rmp
ldi rmp,0
adc R8,rmp
Convert3:
sts sCmp,R7 ; speichere im SRAM
sts sCmp+1,R8
mov ZL,rAdc0L ; kopiere ADC0 nach Z
mov ZH,rAdc0H
ldi XL,LOW(392)
ldi XH,HIGH(392)
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS10)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS11)
ldi XL,LOW(225)
ldi XH,HIGH(225)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS10)|(1<<CS11)
ldi XL,LOW(60)
ldi XH,HIGH(60)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS12)
cpi ZL,3
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS12)|(1<<CS10)
Convert4:
sts sPre,rmp ; sichere Vorteiler-Kontrollbyte im SRAM
ldi rmp,(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)
sbis pSwtchIn,pbInv ; invertiert?
ldi rmp,(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8_v1_main.html (1 of 2)1/20/2009 7:38:51 PM


Rechteckgenerator ATmega8 - Quellcode Hauptprogramm

(1<<WGM11)
sts sMode,rmp
ret
;
; Schreibe die neuen Werte in TC1
;
UpdateTc1:
lds rmp,sCmp+1 ; setze Compare-Match-Wert A
out OCR1AH,rmp
lds rmp,sCmp
out OCR1AL,rmp
lds rmp,sCmp+1 ; setze Compare-Match-Wert B
out OCR1BH,rmp
lds rmp,sCmp
out OCR1BL,rmp
lds rmp,sCtc+1 ; setze CTC-Wert
out ICR1H,rmp
lds rmp,sCtc
out ICR1L,rmp
lds rmp,sMode ; setze Modus TC1
out TCCR1A,rmp
lds rmp,sPre
out TCCR1B,rmp
ret
;
; **************************************************
; L C D - R O U T I N E N
; **************************************************
;
; Initiieren der LCD
;
InitLcd:
ldi ZH,HIGH(2*LcdInitText)
ldi ZL,LOW(2*LcdInitText)
rjmp LcdInit
;
; Zeige Zeile 1 der LCD an
;
LcdL1:
ldi ZH,HIGH(sLcdL1) ; Z auf Zeile 1 im SRAM
ldi ZL,LOW(sLcdL1)
rjmp LcdLine1
;
; Zeige Zeile 2 der LCD an
;
.IF cLcdLn>1
LcdL2:
ldi ZH,HIGH(sLcdL2) ; Z auf Zeile 2 im SRAM
ldi ZL,LOW(sLcdL2)
rjmp LcdLine2
.ENDIF
;
; Zeige TC1 Parameter in Hex auf LCD-Zeile 1
;
.IF dbghx
LcdHexPar:
rcall LcdHome
lds ZH,sCtc+1
lds ZL,sCtc
rcall Displ4Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds ZH,sCmp+1
lds ZL,sCmp
rcall Displ4Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds rmp,sMode
rcall Displ2Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds rmp,sPre
rcall Displ2Hex
ldi rmp,' '
mov R0,rmp
rjmp LcdChar
Displ4Hex:
mov rmp,ZH
rcall Displ2Hex
mov rmp,ZL
Displ2Hex:
push rmp
swap rmp
rcall Displ1Hex
pop rmp
Displ1Hex:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs Displ1Hex1
subi rmp,-7
Displ1Hex1:
mov R0,rmp
rjmp LcdChar
.ENDIF
;
; **************************************************
; H A U P T P R O G R A M M I N I T
; **************************************************
;
Main:
ldi rmp,HIGH(RAMEND) ; Stapel init
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; Schalter-Inputs init
ldi rmp,(1<<pbTime)|(1<<pbRpm)|(1<<pbInv)|(1<<pbPwm)
out pSwtchOut,rmp
; Init der Signalausgabe-Pins
sbi pSignDdr,pbSignA
sbi pSignDdr,pbSignB
cbi pSignOut,pbSignA
sbi pSignOut,pbSignB
; Init Flaggen
clr rFlg
.IF dbgOn ; debug Berechnungen
ldi rmp,HIGH(cAdc0)
mov rAdc0H,rmp
ldi rmp,LOW(cAdc0)
mov rAdc0L,rmp
ldi rmp,HIGH(cAdc1)
mov rAdc1H,rmp
ldi rmp,LOW(cAdc1)
mov rAdc1L,rmp
ldi rFlg,cFlg
rcall Convert
rcall UpdateTc1
.IF cLcdLn>1
rcall Calc
rcall CalcPw
.ELSE
sbrc rFlg,bPw
rjmp dbgPw
rcall Calc
rjmp dbgloop
dbgPw:
rcall CalcPw
.ENDIF
dbgloop:
rjmp dbgloop
.ENDIF
; Init der LCD
rcall InitLcd
; Init des ADC
ldi rmp,(1<<REFS0) ; setze ADMUX auf Kanal 0
out ADMUX,rmp
ldi rmp,(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; starte Umwandlung Kanal 0
ldi rAdcC,1 ; setze Startwert fuer ADC-Verzoegerung
ldi rmp,(1<<CS02)|(1<<CS00) ; Vorteiler 1024
out TCCR0,rmp
ldi rmp,1<<TOIE0 ; ermoegliche TC0 Ueberlauf Int
out TIMSK,rmp
sei
;
; **************************************************
; H A U P T P R O G R A M M S C H L E I F E
; **************************************************
;
Loop:
sleep
nop
sbrs rFlg,bAdc1 ; ADC fertig Flagge gesetzt?
rjmp Loop ; nein, schlaf weiter
cbr rFlg,1<<bAdc1 ; loesche ADC fertig Flagge
.IF cLcdLn == 1
cbr rFlg,(1<<bTime)|(1<<bRpm)|(1<<bPw)|(1<<bInv)
sbis pSwtchIn,pbPwm
sbr rFlg,1<<bPw
.ELSE
cbr rFlg,(1<<bTime)|(1<<bRpm)|(1<<bInv)
.ENDIF
sbis pSwtchIn,pbInv ; Invertiere Signal?
sbr rFlg,1<<bInv
sbis pSwtchIn,pbTime
sbr rFlg,1<<bTime
sbis pSwtchIn,pbRpm
sbr rFlg,1<<bRpm
rcall Convert ; wandle ADC nach TC1-Werte
rcall UpdateTc1
.IF cLcdLn>1
rcall Calc ; berechne Frequenz
rcall CalcPw ; berechne Pulsweite
rcall LcdL2 ; zeige in Zeile 2 an
.ELSE
sbrc rFlg,bPw ; pruefe of Pulsweite angezeigt
rjmp CPw ; ja, berechne Pulsweite
rcall Calc ; berechne Frequenz
rjmp Loop1 ; und zeige Frequenz an
CPw:
rcall CalcPw ; berechne Pulsweite
.ENDIF
Loop1:
rcall LcdL1 ; zeige Zeile 1 an
.IF dbghx
rcall LcdHexPar
.ENDIF
rjmp Loop ; weiterschlafen
;
; **************************************************
; L C D - R O U T I N E N E I N L E S E N
; **************************************************
;
.INCLUDE "Lcd8_02WO_rect.inc"
;
; Init-Text der LCD
;
LcdInitText:
.IF cLcdLn == 1
.IF cLcdLw == 40
.DB "Rechteck- Generator DG4FAC ATmega8 V1.0 "
.ELSE
.IF cLcdLw == 24
.DB "RechtGenerator M8 V1.0 "
.ELSE
.IF cLcdLw == 20
.DB "RechtGenerator V1.0 "
.ELSE
.IF cLcdLw == 16
.DB "RechtGen M8 V1.0"
.ELSE
.DB "RG M8 V1"
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ELSE
.IF cLcdLw == 40
.DB "Rechteck- Generator DG4FAC ATmega8 V1.0",0x0D
.DB "(C)2006 by info!at!avr-asm-tutorial.net "
.ELSE
.IF cLcdLw == 24
.DB "RechtGenerator M8 V1.0 ",0x0D
.DB "www.avr-asm-tutorial.net"
.ELSE
.IF cLcdLw == 20
.DB "RechtGenerator V1.0",0x0D
.DB "avr-asm-tutorial.net"
.ELSE
.IF cLcdLw == 16
.DB "RechtGen M8
V1.0",0x0D,"avr-asm-tutorial",0x00
.ELSE
.DB "RG M8 V1",0x0D,"avr-
asm"
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.DB 0,0
;
; **************************************************
; K O N V E R S I O N S T A B E L L E
; **************************************************
;
.INCLUDE "rectgen_m8_table.inc"
;

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8_v1_main.html (2 of 2)1/20/2009 7:38:51 PM


Rechteckgenerator ATmega8

Pfad: Home => AVR-Übersicht => Anwendungen => Rechteckgenerator

Rechteckgenerator mit ATmega8


Diese Anwendung eines AVR beschreibt einen Rechteckgenerator mit
dem ATMEL ATmega8 mit folgenden Eigenschaften:

● Einstellbarer Frequenzbereich: 0,25 Hz bis 8 MHz in 1024 Stufen


● Weiter Dynamikbereich der Frequenz ohne mechanisches Umschalten
● Umprogrammierung des Frequenzverlaufs möglich
● Einstellbare Pulsweite von 0,00 bis 100,00% in 1024 Stufen
● Pulsweiteneinstellung und Frequenz unabhängig voneinander
● Quarzbasis 16 MHz für stabile Frequenz
● Normaler und invertierter Ausgang
● Umschaltbare Polarität der Ausgänge (aktiv high, aktiv low)
● LCD-Anzeige mit umschaltbarer Anzeige von Frequenz, Zeit, Runden pro Minute, Pulsweite
● Anpassbar an ein- und zweizeilige LCD-Anzeigen mit 16 bis 40 Zeichen pro Zeile
● Englische oder deutsche Anzeigeversion wählbar

0. Inhalt
● 1. Hardware
❍ 1.1 Prozessorteil

❍ 1.2 ISP-Interface

❍ 1.3 LCD-Anzeige

❍ 1.4 Externe Anschlässe

■ 1.4.1 Einstellpotis

■ 1.4.2 Schalter

■ 1.4.3 Ausgangsbuchsen

❍ 1.5 Netzteil

❍ 1.6 Aufbauhinweise

● 2. Bedienung
❍ 2.1 Schalter

❍ 2.2 Ausgangssignale

● 3. Funktionsweise
❍ 3.1 Prozessorteil

❍ 3.2 LCD-Anzeige

❍ 3.3 ISP-Interface

● 4. Software
❍ 4.1 Einstellungen vor dem Assemblieren

❍ 4.2 Frequenztabelle

❍ 4.3 Diverse Schalter

❍ 4.4 Kommentierter Quellcode

1 Hardware
D

Hardware besteht aus dem AVR-Prozessor ATmega8, einem In-System-Programmieranschluss (ISP), einer LCD-Anzeige
und diversen externen Anschlüssen.

1.1 Prozessorteil

Der Prozessor ist mit folgenden externen Komponenten beschaltet.


Die Betriebsspannung von 5 V wird über die Pins 7 (+5 V) und 8 (0 V) zugeführt und mit einem Keramikkondensator
abgeblockt.
Pin 1 (= RESET-Eingang) liegt über einen Widerstand an der positiven Betriebsspannung. An den beiden Anschlüssen Pin 9
und 10 (XT1, XT2) ist ein Quarz mit 16 Mhz angeschlossen. Die Umschaltung des Prozessortakts auf den externen Quarz
erfolgt durch Setzen der entsprechenden Fuses. Die beiden Quarzanschlüsse sind mit Keramikkondensatoren von 22 pF zur
Verbesserung des Anschwingverhaltens des internen Oszillators versehen.
Die Betriebsspannung für den AD-Wandler wird über eine Drossel von 22 µH und einen Folienkondensator von 100 nF an
Pin 20 (AVCC) zugeführt. Als Referenzspannung dient eine softwareseitige Zuschaltung von AVCC, daher ist der AREF-
Pin 21 mit einem Folienkondensator gegen Masse geblockt.

1.2 ISP-Interface

Das ISP-Interface dient der Programmierung des AVR in der fertig aufgebauten Schaltung.
Für ISP verwendet werden die Portbits 5 (SCK), 4 (MISO), und 3 (MOSI) sowie der RESET an Pin 1. MISO dient auch der
Ansteuerung der LCD. Die Belegung am 10-poligen ISP-Pfostenstecker entspricht dem ATMEL-/KANDA-Standard. Die am
Pfostenstecker angeschlossene LED zeigt den aktiven Programmiervorgang an.

1.3 LCD-Anzeige

Angeschlossen ist eine Standard-LCD-Anzeige. Für leichtes Wechseln der Anzeige ist ein 14-poliger Pfostenstecker
vorgesehen, der der 14-poligen Anschlussleiste der LCD entspricht.
Der Kontrollport der LCD ist an die Portbits PB0 (LCD-Enable) und PB4 (LCD-RS-Eingang) angeschlossen. LCD-Enable ist
über einen Widerstand mit 0 V verbunden. Solange der Port B nicht initialisiert ist (nach dem Einschalten, beim
Programmieren über ISP), ist dadurch sichergestellt, dass die LCD nicht durch Fehlsignale angesteuert wird. Der Eingang
LCD-R/W ist dauerhaft mit 0 V verbunden, weil die Anzeige ausschließlich beschrieben wird und nicht ausgelesen werden
muss.
Der Datenport der LCD ist mit allen acht Bits des Ports D verbunden. Die Ansteuerung der LCD erfolgt also 8-bittig.

1.4 Externe Anschlässe

Bis auf die LCD und die Stromversorgung, die über eigene Steckverbinder angeschlossen sind, sind alle weiteren externen
Komponenten über einen 14-poligen Steckverbinder angeschlossen. Dadurch ist sichergestellt, dass die Platine ausgebaut und
ohne diese Komponenten betrieben und getestet werden kann. Durch Auftrennung des Flachbandkabels können die externen
Komponenten systematisch angeschlossen werden.

1.4.1 Einstellpotis

Die ersten vier Adern des Flachbandkabels sind mit der Betriebsspannung und den AD-Kanälen verbunden.
Die beiden AD-Wandlerkanäle ADC0 (Frequenz) und ADC1 (Pulsweite) sind an die Schleifer von 10-Gang-Potentiometern
angeschlossen. Die Potentiometer sind an die Betriebsspannung angeschlossen. Ihr nominaler Widerstandswert und ihre
Linearität sind unkritisch, weil die Einstellungen über die Anzeige kontrolliert werden können.
Direkt am Potentiometer sind die eingestellten Spannungen mit Folienkondensatoren abgeblockt, um eingestreute
Wechselspannungen zu vermeiden.

1.4.2 Schalter

Die nächsten fünf Adern verbinden die Schalter mit den Porteingängen PC2 bis PC5. Der Schalter an PC5 ist nur notwendig,
wenn eine einzeilige LCD-Anzeige verwendet wird. Bei Anschluss einer zweizeiligen LCD ist dieser Schalter wirkungslos.
Alle Schalter verbinden im geschlossenen Zustand den entsprechenden Porteingang mit 0 V, da die inaktiven Eingänge
mittels der Software mit Pullup-Widerständen auf die Betriebsspannung gezogen werden.

1.4.3 Ausgangsbuchsen

Die folgenden drei Adern führen die Ausgänge des Timers (normal, invertiert) an die CINCH-Ausgangsbuchsen.
Die Ausgänge liefern Rechteckspannungen mit den Ausgangscharakteristika der AVR-Treiber und liegen
gleichspannunsgekoppelt an den Buchsen. Die Ausgänge sind kurzschlusssicher, aber gegen extern anliegende Spannungen
nicht geschützt.

1.5 Netzteil

Das Netzteil liefert eine stabilisierte Betriebsspannung von 5 V bei einem Strom von etwa 20 mA. Der Stromverbrauch ist
vom Widerstandswert der Potentiometer abhängig. Prozessor und LCD-Anzeige bleiben unter 10 mA Verbrauch.
Um einen Trafo mit 6 V Sekundärspannung verwenden zu können, ist die Gleichrichterbrücke mit Schottky-Dioden
aufgebaut und ein Low-Drop-Spannungsregler eingesetzt. Bei Trafos mit 7,5 V Sekundärspannung und mehr können diese
Komponenten gegen Standardwerte ausgetauscht werden.
Der Ladekondensator ist großzügig dimensioniert, bei dem geringen Strom kann er auch kleiner gewählt werden.
Die beiden Tantal-Elkos blocken Schwingneigungen des Spannungsreglers ab.

1.6 Aufbauhinweise

Der
Aufbau ist
mit einer
Lochrasterpla
recht
unkritisch.
Der 14-
polige
Anschluss
der LCD
ist links
angeordnet,
der
ebenfalls
14-polige
Anschluss
zu den
externen
Bedieneleme
(Potis,
Schalter,
Ausgangsbuc
rechts auf
der
Platine.
Das
Flachbandkab
ist so
belegt,
dass es zu vier, fünf, drei und zwei Adern aufgetrennt werden kann und übersichtlich den verschiedenen Sektionen zugeführt
werden kann. Wichtig sind die beiden Folienkondensatoren direkt an den Schleifern der beiden Potis, die eingestreute HF/NF
abblocken.
Der 10-polige ISP-Programmieranschluss wird nicht oft benötigt und ist daher nicht außen am Gehäuse zugänglich
angebracht. Das kleine Netzteil sitzt links oben an der Gehäusewand.

2 Bedienung
Nach dem Einschalten zeigt die LCD-Anzeige für etwa 2,5 Sekunden eine Meldung zur Gerätefunktion, die Softwareversion
und das Copyright der Software an. Danach ist das Gerät betriebsbereit.

2.1 Schalter

Mit dem Schalter Time wird zwischen der LCD-Ausgabe der Frequenz (Schalter offen) und der Zeit (Schalter geschlossen)
umgeschaltet. Die Ausgabe der Frequenz erfolgt in Hz mit zwei Dezimalstellen, die Ausgabe der Zeit in Mikrosekunden.
Beide Größen werden gerundet und mit Tausenderzeichen getrennt dargestellt.
Ist die Frequenzausgabe ausgewählt, dann kann mit dem Schalter Rpm die Ausgabe von Umdrehungen pro Minute (= 60 * f)
ausgewählt werden. Ist die Ausgabe der Zeit gewählt, bleibt dieser Schalter unwirksam.
Mit dem Schalter Inv werden beide Ausgangssignale invertiert.
Bei einzeiligen LCD-Anzeigen bewirkt der Schalter Pulse, dass anstelle der Frequenz/Zeit die Pulsweite in % angezeigt wird.
Bei zweizeiligen LCDs beibt dieser Schalter unwirksam, die Pulsweite wird dauernd in der zweiten Zeile angezeigt.

2.2 Ausgangssignale

Die Ausgangssignale stehen an den beiden CINCH-Buchsen in positiver und invertierter Form zur Verfügung. Um kapazitive
Effekte auf die Flankensteilheit zu vermeiden, sollten kurze und unabgeschirmte Leitungen verwendet werden.

3 Funktionsweise
Dieser Abschnitt erläutert die Funktionsweise des Prozessorteils, des ISP-Interfaces und der LCD-Anzeige.

3.1 Prozessorteil

Der Prozessor ATmega8 arbeitet mit einem extern angeschlossenen Quarz als Taktgenerator. Da der Prozessor als
Werkseinstellung mit dem internen RC-Oszillator bei 1 MHz arbeitet, müssen zuerst folgende Fuses des Mega8 umgestellt
werden:

● CKOPT = 0
● CLKSEL3..CKSEL0 = 1111
● SUT1..SUT0 = 11 oder 10

Das Umprogrammieren dieser Fuses kann entweder extern in einem Programmierboard (z.B. mit einem STK500 und dem
ATMEL-Studio) erfolgen oder in der fertig aufgebauten Schaltung mit dem ISP-Interface (z.B. mit PonyProg2000).

Beim Programmieren mit einem STK500 muss


der Quarz zugeschaltet werden, da der Mega8
sonst nach dem Umstellen der Fuses ohne Quarz
nicht mehr ansprechbar ist. Die Fuses sind
richtig eingestellt, wenn eine der beiden letzten
Optionen gewählt wird.

Bei PonyProg ist zu


beachten, dass die
Fuses invertiert
dargestellt sind. Zur
Orientierung: per
Werkseinstellung sind
CKSEL3..CKSEL0
auf 0001 und SUT1..
SUT0 auf 10
eingestellt. Mit dem
Read-Button sollten
die Fuses vorher
ausgelesen werden.
Natürlich muss der
Quarz in der
Schaltung vor dem
Umprogrammieren
der Fuses schon angeschlossen sein. Bei SUT0 kann ebenfalls der Haken ebenfalls entfernt werden (SUT1:SUT0 = 11).

Die angeschlossenen Schalter werden zu Beginn des Programms mittels Software mit den Pull-Up-Widerständen auf
positives Betriebsspannungs-Niveau gezogen. Sind die Schalter eingeschaltet (aktiviert), werden diese Eingangsleitungen auf
logisch Null gesetzt. Der Schalter Pulse ist nur relevant, wenn eine einzeilige LCD-Anzeige verwendet wird.

Die Frequenzerzeugung erfolgt mit dem internen 16-Bit-Zähler TC1 des ATmega8 im Fast-PWM-Modus. Das Schema zeigt
die Funktionsweise des TC1 im Fast-PWM-Modus und die die Funktionen beeinflussenden Parameter (blau).

Die aus
dem
Quarz

abgeleitete 16MHz-Taktfrequenz wird dazu im Vorteiler entweder durch 1, 8, 64, 256 oder 1024 geteilt und dem Zähler
zugeführt. Bei Erreichen des eingestellten TOP-Wertes in dem Doppelregister ICR1 setzt der Zähler zurück und aktiviert die
Compare-Ausgänge OC1A (Portbit PB1, Pin 15) und OC1B (Portbit PB2, Pin 16). Die Frequenz des Generators wird über
den TOP-Wert in ICR1 festgelegt. Abhängig vom eingestellten Wert der Pulsweite werden die Vergleichswerte in den
COMPA- und COMPB-Doppelregistern eingestellt. Erreicht der Zähler diese eingestellten Werte, werden die Ausgänge
OC1A und OC1B deaktiviert und bleiben bis zum Erreichen von TOP inaktiv.
Die beiden Ausgänge OC1A und OC1B sind von der Software komplementär eingestellt, d.h. sie erzeugen invertierte Signale
gleicher Pulsdauer. Mit dem Schalter "Invert" wird diese Polarität an den Ausgängen software-mäßig invertiert.

Die Frequenzeinstellung erfolgt mit dem Potentiometer P1. Da 1024 verschiedene diskrete Frequenzen eingestellt werden
können, muss dafür ein Zehngang-Poti verwendet werden. Das Poti gibt eine Spannung zwischen 0 und 5 V ab, die mit dem
AD-Wandler ADC0 (Portpin PC0, Pin 23) gemessen und in einen Hex-Wert zwischen 0x00 und 0x1F umgewandelt wird.
Dieser Wert wird verwendet, um aus der einprogrammierten Tabelle (Lookup-Tabelle, Include-Datei rectgen_m8_table.inc)
den zugehörigen TOP-Wert auszulesen, der beim nächsten Update in ICR1 geschrieben wird. Abhängig von der eingestellten
Frequenz wird aus dem ADC0-Wert auch noch der Vorteilerwert des Zählers ermittelt und gespeichert.

Die Pulsweiteneinstellung wird mit dem zweiten Zehngang-Potentiometer aufgenommen und über ADC1 (Portbit PC1, Pin
24) in einen Wert zwischen 0x00 und 0x1F umgewandelt. Der TOP-Wert wird mit diesem gemessenen Wert multipliziert
und durch 1024 geteilt. Das Ergebnis wird beim nächsten Update in die Compare-Register COMPA und COMPB
geschrieben.
Im gleichen Zyklus wird noch der Schalter Invert eingelesen und die Ausgangspolarität an OC1A und OC1B eingestellt.

Der TC1-Zähler läuft ohne Software-Eingriff freilaufend. Zum Aktualisieren der Einstellungen wird der 8-Bit-Zähler TC0
verwendet. Er teilt den Systemtakt durch 1024 (Vorteiler) und läft bei Erreichen eines Zählerstandes von 256 über
(@16MHz: alle 16,384 ms). Er unterbricht den Programmablauf und zählt ein Register von 30 abwärts. Wird das
Zählerregister Null (nach jeweils 492 ms), wird der AD-Wandler auf Kanal 0 eingestellt und die erste Messung auf ADC0
gestartet.
Der AD-Wandler arbeitet mit einer durch 128 geteilten Taktfrequenz. Das Vorliegen des ersten Resultats löst einen ADC-
Conversion-Complete-Interrupt aus. Nach Setzen eines Flagbits wird der ADC auf Kanal 1 umgestellt und erneut eine
Messung gestartet. Liegt auch dessen Ergebnis vor, wird der AD-Wandler abgeschaltet und ein Behandlungsflag gesetzt.
Die Umwandlung und Aktualisierung der TC1-Parameter erfolgt danach asynchron in der Hauptprogrammschleife. Die
eingelesenen Werte werden umgewandelt und der Zähler auf die neuen Sollwerte gesetzt. Nach dem Programmieren von
TC1 wird die LCD aktualisiert und der Hauptprogrammloop bis zum nächsten TC0-Interrupt mit Schlafen der CPU
abgeschlossen.

3.2 LCD-Anzeige

Die LCD-Anzeige ist mit dem 8-Bit-Datenport und den beiden Kontrollleitungen E(nable) und R(egister)S(elect) an den
Prozessor angeschlossen. Die R(ead)/W(rite)-Leitung liegt dauernd auf Write, da die gesamte Steuerung über zeitgenaue
Schleifen vorgenommen wird.

Beim Programmstart wird nach einer Wartezeit für die interne Initialisierung die LCD-Anzeige auf folgende Modi
eingestellt:

● 8-Bit-Interface
● Ein- oder zweizeilige LCD (je nach Voreinstellung)
● keine Display-Shift
● Cursor aus
● Blinken aus

Dann wird für 2,5 Sekunden eine Eröffnungsmeldung ausgegeben.

Nach jeder Aktualisierung des TC1-Timers wird auch die Anzeige der LCD aktualisiert. Dazu wird zunächst der CTC-Wert
aus ICR1 mit dem Vorteilerwert (1, 8, 64, 256, 1024) multipliziert. Ist die Anzeige der Frequenz ausgewählt (Schalter Time
aus), dann wird die mit 100 multiplizierte Taktfrequenz (100*16.000.000) durch diesen Wert geteilt, um die Frequenz in Hz
mit einer Auflösung von 0,01 Hz als Ganzzahl zu erhalten. Ist die Zeit ausgewählt (Schalter Time an), wird die mit dem
Vorteilerwert multiplizierte CTC-Rate mit dem Faktor 25.600.000.000/clock (@16MHz: 1.600) multipliziert, um die Zeit in
Mikrosekunden mal 100 als Ganzzahl zu erhalten. Bei einer zweizeiligen LCD wird der sich ergebende Wert für die
Frequenz bzw. die Zeit in Zeile 1 ausgegeben, bei einer einzeiligen LCD nur dann, wenn der Schalter für die Ausgabe der
Pulsweite (Schalter Pulse) nicht aktiviert ist.

Die Pulsweite wird ermittelt, indem der Wert für COMPA bzw. COMPB mit 10.000 multipliziert und dann durch den CTC-
Wert geteilt wird. Die erhaltene Ganzzahl gibt die Pulsweite mal 100 in % an und wird bei einer zweizeiligen LCD in Zeile 2,
bei einer einzeiligen LCD bei eingeschaltetem Schalter Pulse in Zeile 1 mit einer Auflösung von 0,01% angezeigt.
Die Anzeige wird ca. zwei Mal pro Sekunde aktualisiert.

Bei höheren Frequenzen können aufgrund der auf 16 Bit begrenzten Auflösung Frequenzen und Pulsweiten nicht mehr exakt
eingestellt werden. Dies ist dadurch erkennbar, dass Nachkommastellen auftreten. Durch die Berechnung der beiden Größen
aus den tatsächlich verwendeten Werten wird sichergestellt, dass die angezeigten Größen auf jeden Fall zuverlässig sind.

3.3 ISP-Interface

Das ISP-Interface dient der Aktualisierung der Software innerhalb der fertig betriebenen Schaltung. Die Daten- bzw.
Taktsignale MOSI, MISO und SCK sind an einem 10-poligen Standard-Pfostenstecker angelegt. Über die RESET-Leitung
(Portbit PC6, Pin 1) schaltet das ISP-Programmierinterface den Mega8 in den Programmiermodus, nach dem Ende des
Programmierens wird der RESET-Eingang wieder freigegeben und ein Neustart des Prozessor ausgelöst.
Die Programmier-LED zeigt einen aktiven Programmierzyklus an, dient ausschließlich diesem Zweck und kann ersatzlos
entfallen, wenn diese Funktion nicht erforderlich ist oder wenn ein sechspoliger Programmieranschluss verwendet wird.

4 Software
Die Software ist ausschließlich in Assembler geschrieben und in drei funktionelle Pakete aufgeteilt. Vor dem Assemblieren
müssen eine Reihe von Einstellungen vorgenommen werden, um die Software an die vorhandene Hardware optimal
anzupassen.

4.1 Einstellungen vor dem Assemblieren

4.1.1 Frequenztabelle

Die Frequenztabelle in der Datei rectgen_m8_table.inc umfasst 1024 Worte für die Umsetzung der eingestellten Spannung in
den CTC-Wert. Die Werte wurden mit einem Spreadsheet errechnet und als Include-Text-Datei exportiert. Bei Änderungen
an dieser Tabelle ist zu beachten, dass die Übergänge zwischen den verschiedenen Vorteilerwerten in der Routine Convert in
der Datei rectgen_m8_v1.asm ebenfalls an die geänderte Tabelle angepasst werden müssen (aktuelle Werte: 392, 225, 60 und
3).

Wird die Taktfrequenz (Konstante clock) geändert, müssen auch die zugehörigen 5-Byte-Konstanten cDivFx und cDivUx
entsprechend angepasst werden, da bei der automatischen Berechnung Überläufe auftreten würden.

Die Konstanten cLcdLw und cLcdLn definieren die angeschlossene LCD.

Die Konstante cLcdMicro definiert das Mikrozeichen auf der angeschlossenen LCD. Der Default ist auf ein u eingestellt, da
der häufige Wert 0xE4 nicht auf allen LCDs funktioniert.

Die Konstante cEn stellt die Tausender- und Dezimaltrennzeichen auf englisches Format um.

4.1.2 Diverse Schalter

Die Anschlussfolge der Schalter Time, Rpm, Inv und Pulse lässt sich bei der Definition der Ports umstellen (Konstanten
pbTime, pbRpm, pbInv und pbPwm).
Die Schalter dbgon und dbghx dienen dem Debugging. Sie müssen für ordnungsgemäße Funktion des Progamms auf Null
gesetzt sein.

4.2 Kommentierter Quellcode

Der kommentierte Quellcode steht im HTML-Format

● Hauptprogramm
● LCD-Routinen
● Frequenztabelle

und als Assembler-Quellcode gezippt zur Verfügung: alles in einem Paket

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8.html1/20/2009 7:39:10 PM
Rechteckgenerator ATmega8 - Quellcode LCD-Routinen

Pfad: Home => AVR-Übersicht => Anwendungen => Rechteckgenerator = > Quellcode LCD-
Routinen

Rechteckgenerator mit
ATmega8 - Quellcode
LCD-Routinen

;
; *******************************************************
; * Include-Routinen zur LCD-Ansteuerung, stellt die *
; * Basisroutinen fuer die Initiierung einer LCD und die*
; * Textausgabe zur Verfuegung, ausgelegt fuer ein- und *
; * mehrzeilige LCDs, 8-bit-interface, HD44780-kompati- *
; * ble Displays *
; * (C)2006 by g.schmidt, info!at!avr-asm-tutorial.net *
; *******************************************************
;
;
; Charakteristiken der Hardware:
;
.EQU pLcdDataOut = PORTD ; Daten-Port mit dem LCD verbunden ist
.EQU pLcdDataIn = PIND ; dto., der Eingabe-Port
.EQU pLcdDataDir = DDRD ; dto., Port-Richtung
.EQU pLcdEOut = PORTB ; Kontroll-Port Bit E der LCD
.EQU pLcdEDir = DDRB ; dto., Richtungs-Bit
.EQU pLcdRsOut = PORTB ; dto., Bit LCD-RS der LCD
.EQU pLcdRsDir = DDRB ; dto., Richtungs-Bit
.EQU bLcdEOut = 0 ; Port-Bit E der LCD
.EQU bLcdRSOut = 4 ; Port-Bit RS der LCD
;
; Weitere Bedingungen zum Assemblieren:
;
; Typ Name Erlaeuterung
; -----------------------------------------------------------
; Konstante Clock Prozessorfrequenz in Hz, Bereich 1..16 MHz
; cLcdLw Anzahl Zeichen pro Zeile der LCD
; cLcdLn Anzahl Zeilen der LCD (1 oder 2)
; Register rmp Multi-Purpose Register (R16..R31)
; -----------------------------------------------------------
;
; Stellt folgende Routinen zur Verfuegung:
;
; Name Parameter Erfuellt folgende Aufgaben
; ---------------------------------------------------------
; LcdInit Z:Text1 im Flash Initiiert die LCD and zeigt
; Speicher (null- den Text1 an auf den Z zeigt,
; terminiert), wartet fuer 1.5 Sekunden und
; Zeilen durch
; getrennt
; X:Text2 im Flash zeigt Text2 an, auf den X
; Verwendet R25:R24 zeigt
; LcdFlash Z: Text im Flash Zeigt den Text im Flash-
; speicher an, auf den Z zeigt
; LcdHome -- Setzt die Anzeigenposition
; den Beginn von Zeile 1
; LcdChar R0 = Zeichen Schreibt das Zeichen in R0
; an die aktuelle LCD-Position
; LcdLine1 Z:Text im SRAM Zeigt den Text im SRAM auf
; Zeile 1 der LCD an
; LcdLine2 Z:Text im SRAM Zeigt den Text im SRAM auf
; Zeile 2 der LCD an
; -----------------------------------------------------
;
; -----------------------------------------------
; L C D I N I T I I E R U N G R O U T I N E
; -----------------------------------------------
;
LcdInit:
cbi pLcdEOut,bLcdEOut ; loesche LCD Enable Bit
sbi pLcdEDir,bLcdEOut ; E-Bit ist Ausgang
sbi pLcdRsDir,bLcdRSOut ; dto., RS-Bit
rcall Delay360ms ; warte auf die LCD-interne Initiierung
ldi rmp,0xFF ; setze LCD-Datenport auf Ausgang
out pLcdDataDir,rmp
rcall Delay15ms ; warte 15 ms fuer interne Initiierung
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
ldi rmp,0x08 ; Display abschalten
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
ldi rmp,0x01 ; Display loeschen
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay1m64s ; warte 1.64 ms
ldi rmp,0x06 ; Increment ein, Shift aus
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
ldi rmp,0x0C ; activiere Display, kein Cursor, kein Blinken
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall LcdHome ; setze Cursorposition auf Anfang Zeile 1
rcall LcdFlash ; Schreibe Text im Flash ab Z auf Display
rjmp Delay2s5 ; warte fuer 2.5 Sekunden
;
; -------------------------------------------------
; L C D S C H R E I B - S U B R O U T I N E N
; -------------------------------------------------
;
; Schreibe Text ab Position Z im Flash auf Display
;
LcdFlash:
lpm ; lese naechstes Zeichen aus dem Flashspeicher
tst R0 ; Ende des Textes erreicht?
breq LcdFlash2
.IF cLcdLn>1
ldi rmp,0x0D ; Wagenruecklauf-Zeichen?
cp rmp,R0
brne LcdFlash1 ; zeige Zeichen an
ldi rmp,0xC0 ; Adresse von Zeile 2
rcall LcdStrobeC ; an Kontrollport der LCD
rcall Delay40us ; 40 us Verzoegerung
adiw ZL,1 ; naechstes Zeichen
rjmp LcdFlash ; und weiter
LcdFlash1:
.ENDIF
out pLcdDataOut,R0 ; Zeichen in R0 an Datenport
sbi pLcdRsOut,bLcdRSOut ; setze RS-Bit
rcall LcdStrobeE ; E-Bit pulsen
cbi pLcdRsOut,bLcdRSOut ; loesche RS-Bit
rcall Delay40us ; 40 us Verzoegerung
adiw ZL,1
rjmp LcdFlash ; naechtes Zeichen
LcdFlash2:
ret
;
; Setzt die LCD-Ausgabeposition auf den Anfang von Zeile 1
;
LcdHome:
ldi rmp,0x02 ; setze Kontrollwort fuer Home
rcall LcdStrobeC ; schreibe Kontrollwort
rjmp Delay1m64s ; warte 1,64 ms
;
; gibt das Zeichen in rmp als Kontrollwort aus und pulst das E-Bit
;
LcdStrobeC:
out pLcdDataOut,rmp ; schreibe Kontrollwort auf Datenport
cbi pLcdRsOut,bLcdRSOut ; loesche RS-Bit
;
; Pulst E-Bit mit korrekter Dauer
;
LcdStrobeE:
sbi pLcdEOut,bLcdEOut ; setze E-Bit Eins
nop ; warte mindestens 1 Zyklus
.IF Clock>2 ; mehr als 2 MHz Takt
nop ; zwei NOP
.ENDIF
.IF Clock>4 ; mehr als 4 MHz Takt
nop ; drei NOP
.ENDIF
.IF Clock>6 ; mehr als 6 MHz Takt
nop ; vier NOP
.ENDIF
.IF Clock>8 ; mehr als 8 MHz Takt
nop ; fuenf NOP
.ENDIF
.IF Clock>10 ; mehr als 10 MHz Takt
nop ; sechs NOP
.ENDIF
.IF Clock>12 ; mehr als 12 MHz Takt
nop ; sieben NOP
.ENDIF
.IF Clock>14 ; mehr als 14 MHz Takt
nop ; acht NOP
.ENDIF
cbi pLcdEOut,bLcdEOut ; loesche E-Bit
rjmp Delay40us ; Verzoegerung 40 us
;
; Zeige Zeichen in R0 an
;
LcdChar:
out pLcdDataOut,R0 ; Ausgabe des Zeichens in R0
sbi pLcdRsOut,bLcdRSOut ; setze RS-Bit
rjmp LcdStrobeE ; pulse E-Bit
;
; Zeigt den Text ab Z im SRAM auf Zeile 1 der LCD an
;
LcdLine1:
ldi rmp,0x80 ; setze Cursor auf Zeile 1
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine1a:
ld R0,Z+ ; lese naechstes Zeichen aus SRAM
rcall LcdChar
dec rmp
brne LcdLine1a
ret
;
; Zeigt den Text ab Z im SRAM auf Zeile 2 der LCD an
;
LcdLine2:
ldi rmp,0xC0 ; setze Cursor auf Zeile 2
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine2a:
ld R0,Z+ ; lese naechstes Zeichen aus SRAM
rcall LcdChar
dec rmp
brne LcdLine2a
ret
;
; -------------------------------------------------------------
; V E R Z O E G E R U N G S R O U T I N E N F U E R L C D
; -------------------------------------------------------------
;
.SET clockus = clock/1000000
.IF clockus == 0 ; Clock kleiner als 1 MHz
.SET clockus = 1
.ENDIF
;
; Verzoegerung fuer 2.5 Sekunden
;
Delay2s5:
push rmp
ldi rmp,2500/15+1 ; Anzahl 15ms-Verzoegerungen
Delay2s5a:
rcall Delay15ms
dec rmp
brne Delay2s5a
pop rmp
ret
;
; Verzoegerung fuer 360 Millisekunden
;
Delay360ms:
push rmp
ldi rmp,360/15+1 ; Anzahl der 15ms-Verzoegerungen
Delay360ms1:
rcall Delay15ms
dec rmp
brne Delay360ms1
pop rmp
ret
;
; Verzoegerung fuer 15 Millisekunden
;
Delay15ms:
push ZH ; sichere Z
push ZL
ldi ZH,HIGH((15000*clockus-16)/4)
ldi ZL,LOW((15000*clockus-16)/4)
Delay15ms1:
sbiw ZL,1
brne Delay15ms1
pop ZL
pop ZH
ret
;
; Verzoegerung fuer 1.64 Millisekunden
;
Delay1m64s:
push ZH ; sichere Z
push ZL
ldi ZH,HIGH((1640*clockus-16)/4)
ldi ZL,LOW((1640*clockus-16)/4)
Delay1m64s1:
sbiw ZL,1
brne Delay1m64s1
pop ZL
pop ZH
ret
;
; Verzoegerung 40 Mikrosekunden
;
Delay40us:
push rmp
ldi rmp,(40*clockus-11)/3
Delay40us1:
dec rmp
brne Delay40us1
pop rmp
ret
;
; Ende der LCD-Routinen
;

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8_v1_lcd.html1/20/2009 7:39:17 PM
Rechteckgenerator ATmega8 - Quellcode Frequenztabelle

Pfad: Home => AVR-Übersicht => Anwendungen => Rechteckgenerator = > Quellcode
Frequenztabelle

Rechteckgenerator mit
ATmega8 - Quellcode
Frequenztabelle

; Tabelle fuer die Umwandlung von ADC-Werten zu TC1-Compare-Werten


; TC1-Vorteiler: n<3: 1024, n<60: 256, n<225: 64, n<392: 8,
darueber: 1
DataTable: ; 16MHz-Zaehler TC1
.DW 0 ; nAdc= 0, f= aus
.DW 62500 ; nAdc= 1, f= 0,25, upm= 15
.DW 31250 ; nAdc= 2, f= 0,5, upm= 30
.DW 62500 ; nAdc= 3, f= 1, upm= 60
.DW 59524 ; nAdc= 4, f= 1,05, upm= 63
.DW 56818 ; nAdc= 5, f= 1,1, upm= 66
.DW 54348 ; nAdc= 6, f= 1,15, upm= 69
.DW 52083 ; nAdc= 7, f= 1,2, upm= 72
.DW 50000 ; nAdc= 8, f= 1,25, upm= 75
.DW 48077 ; nAdc= 9, f= 1,3, upm= 78
.DW 46296 ; nAdc= 10, f= 1,35, upm= 81
.DW 44643 ; nAdc= 11, f= 1,4, upm= 84
.DW 43103 ; nAdc= 12, f= 1,45, upm= 87
.DW 41667 ; nAdc= 13, f= 1,5, upm= 90
.DW 40323 ; nAdc= 14, f= 1,55, upm= 93
.DW 39063 ; nAdc= 15, f= 1,6, upm= 96
.DW 37879 ; nAdc= 16, f= 1,65, upm= 99
.DW 36765 ; nAdc= 17, f= 1,7, upm= 102
.DW 35714 ; nAdc= 18, f= 1,75, upm= 105
.DW 34722 ; nAdc= 19, f= 1,8, upm= 108
.DW 33784 ; nAdc= 20, f= 1,85, upm= 111
.DW 32895 ; nAdc= 21, f= 1,9, upm= 114
.DW 32051 ; nAdc= 22, f= 1,95, upm= 117
.DW 31250 ; nAdc= 23, f= 2, upm= 120
.DW 30488 ; nAdc= 24, f= 2,05, upm= 123
.DW 29762 ; nAdc= 25, f= 2,1, upm= 126
.DW 29070 ; nAdc= 26, f= 2,15, upm= 129
.DW 28409 ; nAdc= 27, f= 2,2, upm= 132
.DW 27778 ; nAdc= 28, f= 2,25, upm= 135
.DW 27174 ; nAdc= 29, f= 2,3, upm= 138
.DW 26596 ; nAdc= 30, f= 2,35, upm= 141
.DW 26042 ; nAdc= 31, f= 2,4, upm= 144
.DW 25510 ; nAdc= 32, f= 2,45, upm= 147
.DW 25000 ; nAdc= 33, f= 2,5, upm= 150
.DW 24510 ; nAdc= 34, f= 2,55, upm= 153
.DW 24038 ; nAdc= 35, f= 2,6, upm= 156
.DW 23585 ; nAdc= 36, f= 2,65, upm= 159
.DW 23148 ; nAdc= 37, f= 2,7, upm= 162
.DW 22727 ; nAdc= 38, f= 2,75, upm= 165
.DW 22321 ; nAdc= 39, f= 2,8, upm= 168
.DW 21930 ; nAdc= 40, f= 2,85, upm= 171
.DW 21552 ; nAdc= 41, f= 2,9, upm= 174
.DW 21186 ; nAdc= 42, f= 2,95, upm= 177
.DW 20833 ; nAdc= 43, f= 3, upm= 180
.DW 20492 ; nAdc= 44, f= 3,05, upm= 183
.DW 20161 ; nAdc= 45, f= 3,1, upm= 186
.DW 19841 ; nAdc= 46, f= 3,15, upm= 189
.DW 19531 ; nAdc= 47, f= 3,2, upm= 192
.DW 19231 ; nAdc= 48, f= 3,25, upm= 195
.DW 18939 ; nAdc= 49, f= 3,3, upm= 198
.DW 18657 ; nAdc= 50, f= 3,35, upm= 201
.DW 18382 ; nAdc= 51, f= 3,4, upm= 204
.DW 18116 ; nAdc= 52, f= 3,45, upm= 207
.DW 17857 ; nAdc= 53, f= 3,5, upm= 210
.DW 17606 ; nAdc= 54, f= 3,55, upm= 213
.DW 17361 ; nAdc= 55, f= 3,6, upm= 216
.DW 17123 ; nAdc= 56, f= 3,65, upm= 219
.DW 16892 ; nAdc= 57, f= 3,7, upm= 222
.DW 16667 ; nAdc= 58, f= 3,75, upm= 225
.DW 16447 ; nAdc= 59, f= 3,8, upm= 228
.DW 64935 ; nAdc= 60, f= 3,85, upm= 231
.DW 64103 ; nAdc= 61, f= 3,9, upm= 234
.DW 63291 ; nAdc= 62, f= 3,95, upm= 237
.DW 62500 ; nAdc= 63, f= 4, upm= 240
.DW 61728 ; nAdc= 64, f= 4,05, upm= 243
.DW 60976 ; nAdc= 65, f= 4,1, upm= 246
.DW 60241 ; nAdc= 66, f= 4,15, upm= 249
.DW 59524 ; nAdc= 67, f= 4,2, upm= 252
.DW 58824 ; nAdc= 68, f= 4,25, upm= 255
.DW 58140 ; nAdc= 69, f= 4,3, upm= 258
.DW 57471 ; nAdc= 70, f= 4,35, upm= 261
.DW 56818 ; nAdc= 71, f= 4,4, upm= 264
.DW 56180 ; nAdc= 72, f= 4,45, upm= 267
.DW 55556 ; nAdc= 73, f= 4,5, upm= 270
.DW 54945 ; nAdc= 74, f= 4,55, upm= 273
.DW 54348 ; nAdc= 75, f= 4,6, upm= 276
.DW 53763 ; nAdc= 76, f= 4,65, upm= 279
.DW 53191 ; nAdc= 77, f= 4,7, upm= 282
.DW 52632 ; nAdc= 78, f= 4,75, upm= 285
.DW 52083 ; nAdc= 79, f= 4,8, upm= 288
.DW 51546 ; nAdc= 80, f= 4,85, upm= 291
.DW 51020 ; nAdc= 81, f= 4,9, upm= 294
.DW 50505 ; nAdc= 82, f= 4,95, upm= 297
.DW 50000 ; nAdc= 83, f= 5, upm= 300
.DW 49505 ; nAdc= 84, f= 5,05, upm= 303
.DW 49020 ; nAdc= 85, f= 5,1, upm= 306
.DW 48544 ; nAdc= 86, f= 5,15, upm= 309
.DW 48077 ; nAdc= 87, f= 5,2, upm= 312
.DW 47619 ; nAdc= 88, f= 5,25, upm= 315
.DW 47170 ; nAdc= 89, f= 5,3, upm= 318
.DW 46729 ; nAdc= 90, f= 5,35, upm= 321
.DW 46296 ; nAdc= 91, f= 5,4, upm= 324
.DW 45872 ; nAdc= 92, f= 5,45, upm= 327
.DW 45455 ; nAdc= 93, f= 5,5, upm= 330
.DW 45045 ; nAdc= 94, f= 5,55, upm= 333
.DW 44643 ; nAdc= 95, f= 5,6, upm= 336
.DW 44248 ; nAdc= 96, f= 5,65, upm= 339
.DW 43860 ; nAdc= 97, f= 5,7, upm= 342
.DW 43478 ; nAdc= 98, f= 5,75, upm= 345
.DW 43103 ; nAdc= 99, f= 5,8, upm= 348
.DW 42735 ; nAdc= 100, f= 5,85, upm= 351
.DW 42373 ; nAdc= 101, f= 5,9, upm= 354
.DW 42017 ; nAdc= 102, f= 5,95, upm= 357
.DW 41667 ; nAdc= 103, f= 6, upm= 360
.DW 41322 ; nAdc= 104, f= 6,05, upm= 363
.DW 40984 ; nAdc= 105, f= 6,1, upm= 366
.DW 40650 ; nAdc= 106, f= 6,15, upm= 369
.DW 40323 ; nAdc= 107, f= 6,2, upm= 372
.DW 40000 ; nAdc= 108, f= 6,25, upm= 375
.DW 39683 ; nAdc= 109, f= 6,3, upm= 378
.DW 39370 ; nAdc= 110, f= 6,35, upm= 381
.DW 39063 ; nAdc= 111, f= 6,4, upm= 384
.DW 38760 ; nAdc= 112, f= 6,45, upm= 387
.DW 38462 ; nAdc= 113, f= 6,5, upm= 390
.DW 38168 ; nAdc= 114, f= 6,55, upm= 393
.DW 37879 ; nAdc= 115, f= 6,6, upm= 396
.DW 37594 ; nAdc= 116, f= 6,65, upm= 399
.DW 37313 ; nAdc= 117, f= 6,7, upm= 402
.DW 37037 ; nAdc= 118, f= 6,75, upm= 405
.DW 36765 ; nAdc= 119, f= 6,8, upm= 408
.DW 36496 ; nAdc= 120, f= 6,85, upm= 411
.DW 36232 ; nAdc= 121, f= 6,9, upm= 414
.DW 35971 ; nAdc= 122, f= 6,95, upm= 417
.DW 35714 ; nAdc= 123, f= 7, upm= 420
.DW 35461 ; nAdc= 124, f= 7,05, upm= 423
.DW 35211 ; nAdc= 125, f= 7,1, upm= 426
.DW 34965 ; nAdc= 126, f= 7,15, upm= 429
.DW 34722 ; nAdc= 127, f= 7,2, upm= 432
.DW 34483 ; nAdc= 128, f= 7,25, upm= 435
.DW 34247 ; nAdc= 129, f= 7,3, upm= 438
.DW 34014 ; nAdc= 130, f= 7,35, upm= 441
.DW 33784 ; nAdc= 131, f= 7,4, upm= 444
.DW 33557 ; nAdc= 132, f= 7,45, upm= 447
.DW 33333 ; nAdc= 133, f= 7,5, upm= 450
.DW 33113 ; nAdc= 134, f= 7,55, upm= 453
.DW 32895 ; nAdc= 135, f= 7,6, upm= 456
.DW 32680 ; nAdc= 136, f= 7,65, upm= 459
.DW 32468 ; nAdc= 137, f= 7,7, upm= 462
.DW 32258 ; nAdc= 138, f= 7,75, upm= 465
.DW 32051 ; nAdc= 139, f= 7,8, upm= 468
.DW 31847 ; nAdc= 140, f= 7,85, upm= 471
.DW 31646 ; nAdc= 141, f= 7,9, upm= 474
.DW 31447 ; nAdc= 142, f= 7,95, upm= 477
.DW 31250 ; nAdc= 143, f= 8, upm= 480
.DW 31056 ; nAdc= 144, f= 8,05, upm= 483
.DW 30864 ; nAdc= 145, f= 8,1, upm= 486
.DW 30675 ; nAdc= 146, f= 8,15, upm= 489
.DW 30488 ; nAdc= 147, f= 8,2, upm= 492
.DW 30303 ; nAdc= 148, f= 8,25, upm= 495
.DW 30120 ; nAdc= 149, f= 8,3, upm= 498
.DW 29940 ; nAdc= 150, f= 8,35, upm= 501
.DW 29762 ; nAdc= 151, f= 8,4, upm= 504
.DW 29586 ; nAdc= 152, f= 8,45, upm= 507
.DW 29412 ; nAdc= 153, f= 8,5, upm= 510
.DW 29240 ; nAdc= 154, f= 8,55, upm= 513
.DW 29070 ; nAdc= 155, f= 8,6, upm= 516
.DW 28902 ; nAdc= 156, f= 8,65, upm= 519
.DW 28736 ; nAdc= 157, f= 8,7, upm= 522
.DW 28571 ; nAdc= 158, f= 8,75, upm= 525
.DW 28409 ; nAdc= 159, f= 8,8, upm= 528
.DW 28249 ; nAdc= 160, f= 8,85, upm= 531
.DW 28090 ; nAdc= 161, f= 8,9, upm= 534
.DW 27933 ; nAdc= 162, f= 8,95, upm= 537
.DW 27778 ; nAdc= 163, f= 9, upm= 540
.DW 27624 ; nAdc= 164, f= 9,05, upm= 543
.DW 27473 ; nAdc= 165, f= 9,1, upm= 546
.DW 27322 ; nAdc= 166, f= 9,15, upm= 549
.DW 27174 ; nAdc= 167, f= 9,2, upm= 552
.DW 27027 ; nAdc= 168, f= 9,25, upm= 555
.DW 26882 ; nAdc= 169, f= 9,3, upm= 558
.DW 26738 ; nAdc= 170, f= 9,35, upm= 561
.DW 26596 ; nAdc= 171, f= 9,4, upm= 564
.DW 26455 ; nAdc= 172, f= 9,45, upm= 567
.DW 26316 ; nAdc= 173, f= 9,5, upm= 570
.DW 26178 ; nAdc= 174, f= 9,55, upm= 573
.DW 26042 ; nAdc= 175, f= 9,6, upm= 576
.DW 25907 ; nAdc= 176, f= 9,65, upm= 579
.DW 25773 ; nAdc= 177, f= 9,7, upm= 582
.DW 25641 ; nAdc= 178, f= 9,75, upm= 585
.DW 25510 ; nAdc= 179, f= 9,8, upm= 588
.DW 25381 ; nAdc= 180, f= 9,85, upm= 591
.DW 25253 ; nAdc= 181, f= 9,9, upm= 594
.DW 25126 ; nAdc= 182, f= 9,95, upm= 597
.DW 25000 ; nAdc= 183, f= 10, upm= 600
.DW 23810 ; nAdc= 184, f= 10,5, upm= 630
.DW 22727 ; nAdc= 185, f= 11, upm= 660
.DW 21739 ; nAdc= 186, f= 11,5, upm= 690
.DW 20833 ; nAdc= 187, f= 12, upm= 720
.DW 20000 ; nAdc= 188, f= 12,5, upm= 750
.DW 19231 ; nAdc= 189, f= 13, upm= 780
.DW 18519 ; nAdc= 190, f= 13,5, upm= 810
.DW 17857 ; nAdc= 191, f= 14, upm= 840
.DW 17241 ; nAdc= 192, f= 14,5, upm= 870
.DW 16667 ; nAdc= 193, f= 15, upm= 900
.DW 16129 ; nAdc= 194, f= 15,5, upm= 930
.DW 15625 ; nAdc= 195, f= 16, upm= 960
.DW 15152 ; nAdc= 196, f= 16,5, upm= 990
.DW 14706 ; nAdc= 197, f= 17, upm= 1020
.DW 14286 ; nAdc= 198, f= 17,5, upm= 1050
.DW 13889 ; nAdc= 199, f= 18, upm= 1080
.DW 13514 ; nAdc= 200, f= 18,5, upm= 1110
.DW 13158 ; nAdc= 201, f= 19, upm= 1140
.DW 12821 ; nAdc= 202, f= 19,5, upm= 1170
.DW 12500 ; nAdc= 203, f= 20, upm= 1200
.DW 12195 ; nAdc= 204, f= 20,5, upm= 1230
.DW 11905 ; nAdc= 205, f= 21, upm= 1260
.DW 11628 ; nAdc= 206, f= 21,5, upm= 1290
.DW 11364 ; nAdc= 207, f= 22, upm= 1320
.DW 11111 ; nAdc= 208, f= 22,5, upm= 1350
.DW 10870 ; nAdc= 209, f= 23, upm= 1380
.DW 10638 ; nAdc= 210, f= 23,5, upm= 1410
.DW 10417 ; nAdc= 211, f= 24, upm= 1440
.DW 10204 ; nAdc= 212, f= 24,5, upm= 1470
.DW 10000 ; nAdc= 213, f= 25, upm= 1500
.DW 9804 ; nAdc= 214, f= 25,5, upm= 1530
.DW 9615 ; nAdc= 215, f= 26, upm= 1560
.DW 9434 ; nAdc= 216, f= 26,5, upm= 1590
.DW 9259 ; nAdc= 217, f= 27, upm= 1620
.DW 9091 ; nAdc= 218, f= 27,5, upm= 1650
.DW 8929 ; nAdc= 219, f= 28, upm= 1680
.DW 8772 ; nAdc= 220, f= 28,5, upm= 1710
.DW 8621 ; nAdc= 221, f= 29, upm= 1740
.DW 8475 ; nAdc= 222, f= 29,5, upm= 1770
.DW 8333 ; nAdc= 223, f= 30, upm= 1800
.DW 8197 ; nAdc= 224, f= 30,5, upm= 1830
.DW 64516 ; nAdc= 225, f= 31, upm= 1860
.DW 63492 ; nAdc= 226, f= 31,5, upm= 1890
.DW 62500 ; nAdc= 227, f= 32, upm= 1920
.DW 61538 ; nAdc= 228, f= 32,5, upm= 1950
.DW 60606 ; nAdc= 229, f= 33, upm= 1980
.DW 59701 ; nAdc= 230, f= 33,5, upm= 2010
.DW 58824 ; nAdc= 231, f= 34, upm= 2040
.DW 57971 ; nAdc= 232, f= 34,5, upm= 2070
.DW 57143 ; nAdc= 233, f= 35, upm= 2100
.DW 56338 ; nAdc= 234, f= 35,5, upm= 2130
.DW 55556 ; nAdc= 235, f= 36, upm= 2160
.DW 54795 ; nAdc= 236, f= 36,5, upm= 2190
.DW 54054 ; nAdc= 237, f= 37, upm= 2220
.DW 53333 ; nAdc= 238, f= 37,5, upm= 2250
.DW 52632 ; nAdc= 239, f= 38, upm= 2280
.DW 51948 ; nAdc= 240, f= 38,5, upm= 2310
.DW 51282 ; nAdc= 241, f= 39, upm= 2340
.DW 50633 ; nAdc= 242, f= 39,5, upm= 2370
.DW 50000 ; nAdc= 243, f= 40, upm= 2400
.DW 49383 ; nAdc= 244, f= 40,5, upm= 2430
.DW 48780 ; nAdc= 245, f= 41, upm= 2460
.DW 48193 ; nAdc= 246, f= 41,5, upm= 2490
.DW 47619 ; nAdc= 247, f= 42, upm= 2520
.DW 47059 ; nAdc= 248, f= 42,5, upm= 2550
.DW 46512 ; nAdc= 249, f= 43, upm= 2580
.DW 45977 ; nAdc= 250, f= 43,5, upm= 2610
.DW 45455 ; nAdc= 251, f= 44, upm= 2640
.DW 44944 ; nAdc= 252, f= 44,5, upm= 2670
.DW 44444 ; nAdc= 253, f= 45, upm= 2700
.DW 43956 ; nAdc= 254, f= 45,5, upm= 2730
.DW 43478 ; nAdc= 255, f= 46, upm= 2760
.DW 43011 ; nAdc= 256, f= 46,5, upm= 2790
.DW 42553 ; nAdc= 257, f= 47, upm= 2820
.DW 42105 ; nAdc= 258, f= 47,5, upm= 2850
.DW 41667 ; nAdc= 259, f= 48, upm= 2880
.DW 41237 ; nAdc= 260, f= 48,5, upm= 2910
.DW 40816 ; nAdc= 261, f= 49, upm= 2940
.DW 40404 ; nAdc= 262, f= 49,5, upm= 2970
.DW 40000 ; nAdc= 263, f= 50, upm= 3000
.DW 39604 ; nAdc= 264, f= 50,5, upm= 3030
.DW 39216 ; nAdc= 265, f= 51, upm= 3060
.DW 38835 ; nAdc= 266, f= 51,5, upm= 3090
.DW 38462 ; nAdc= 267, f= 52, upm= 3120
.DW 38095 ; nAdc= 268, f= 52,5, upm= 3150
.DW 37736 ; nAdc= 269, f= 53, upm= 3180
.DW 37383 ; nAdc= 270, f= 53,5, upm= 3210
.DW 37037 ; nAdc= 271, f= 54, upm= 3240
.DW 36697 ; nAdc= 272, f= 54,5, upm= 3270
.DW 36364 ; nAdc= 273, f= 55, upm= 3300
.DW 36036 ; nAdc= 274, f= 55,5, upm= 3330
.DW 35714 ; nAdc= 275, f= 56, upm= 3360
.DW 35398 ; nAdc= 276, f= 56,5, upm= 3390
.DW 35088 ; nAdc= 277, f= 57, upm= 3420
.DW 34783 ; nAdc= 278, f= 57,5, upm= 3450
.DW 34483 ; nAdc= 279, f= 58, upm= 3480
.DW 34188 ; nAdc= 280, f= 58,5, upm= 3510
.DW 33898 ; nAdc= 281, f= 59, upm= 3540
.DW 33613 ; nAdc= 282, f= 59,5, upm= 3570
.DW 33333 ; nAdc= 283, f= 60, upm= 3600
.DW 33058 ; nAdc= 284, f= 60,5, upm= 3630
.DW 32787 ; nAdc= 285, f= 61, upm= 3660
.DW 32520 ; nAdc= 286, f= 61,5, upm= 3690
.DW 32258 ; nAdc= 287, f= 62, upm= 3720
.DW 32000 ; nAdc= 288, f= 62,5, upm= 3750
.DW 31746 ; nAdc= 289, f= 63, upm= 3780
.DW 31496 ; nAdc= 290, f= 63,5, upm= 3810
.DW 31250 ; nAdc= 291, f= 64, upm= 3840
.DW 31008 ; nAdc= 292, f= 64,5, upm= 3870
.DW 30769 ; nAdc= 293, f= 65, upm= 3900
.DW 30534 ; nAdc= 294, f= 65,5, upm= 3930
.DW 30303 ; nAdc= 295, f= 66, upm= 3960
.DW 30075 ; nAdc= 296, f= 66,5, upm= 3990
.DW 29851 ; nAdc= 297, f= 67, upm= 4020
.DW 29630 ; nAdc= 298, f= 67,5, upm= 4050
.DW 29412 ; nAdc= 299, f= 68, upm= 4080
.DW 29197 ; nAdc= 300, f= 68,5, upm= 4110
.DW 28986 ; nAdc= 301, f= 69, upm= 4140
.DW 28777 ; nAdc= 302, f= 69,5, upm= 4170
.DW 28571 ; nAdc= 303, f= 70, upm= 4200
.DW 28369 ; nAdc= 304, f= 70,5, upm= 4230
.DW 28169 ; nAdc= 305, f= 71, upm= 4260
.DW 27972 ; nAdc= 306, f= 71,5, upm= 4290
.DW 27778 ; nAdc= 307, f= 72, upm= 4320
.DW 27586 ; nAdc= 308, f= 72,5, upm= 4350
.DW 27397 ; nAdc= 309, f= 73, upm= 4380
.DW 27211 ; nAdc= 310, f= 73,5, upm= 4410
.DW 27027 ; nAdc= 311, f= 74, upm= 4440
.DW 26846 ; nAdc= 312, f= 74,5, upm= 4470
.DW 26667 ; nAdc= 313, f= 75, upm= 4500
.DW 26490 ; nAdc= 314, f= 75,5, upm= 4530
.DW 26316 ; nAdc= 315, f= 76, upm= 4560
.DW 26144 ; nAdc= 316, f= 76,5, upm= 4590
.DW 25974 ; nAdc= 317, f= 77, upm= 4620
.DW 25806 ; nAdc= 318, f= 77,5, upm= 4650
.DW 25641 ; nAdc= 319, f= 78, upm= 4680
.DW 25478 ; nAdc= 320, f= 78,5, upm= 4710
.DW 25316 ; nAdc= 321, f= 79, upm= 4740
.DW 25157 ; nAdc= 322, f= 79,5, upm= 4770
.DW 25000 ; nAdc= 323, f= 80, upm= 4800
.DW 24845 ; nAdc= 324, f= 80,5, upm= 4830
.DW 24691 ; nAdc= 325, f= 81, upm= 4860
.DW 24540 ; nAdc= 326, f= 81,5, upm= 4890
.DW 24390 ; nAdc= 327, f= 82, upm= 4920
.DW 24242 ; nAdc= 328, f= 82,5, upm= 4950
.DW 24096 ; nAdc= 329, f= 83, upm= 4980
.DW 23952 ; nAdc= 330, f= 83,5, upm= 5010
.DW 23810 ; nAdc= 331, f= 84, upm= 5040
.DW 23669 ; nAdc= 332, f= 84,5, upm= 5070
.DW 23529 ; nAdc= 333, f= 85, upm= 5100
.DW 23392 ; nAdc= 334, f= 85,5, upm= 5130
.DW 23256 ; nAdc= 335, f= 86, upm= 5160
.DW 23121 ; nAdc= 336, f= 86,5, upm= 5190
.DW 22989 ; nAdc= 337, f= 87, upm= 5220
.DW 22857 ; nAdc= 338, f= 87,5, upm= 5250
.DW 22727 ; nAdc= 339, f= 88, upm= 5280
.DW 22599 ; nAdc= 340, f= 88,5, upm= 5310
.DW 22472 ; nAdc= 341, f= 89, upm= 5340
.DW 22346 ; nAdc= 342, f= 89,5, upm= 5370
.DW 22222 ; nAdc= 343, f= 90, upm= 5400
.DW 22099 ; nAdc= 344, f= 90,5, upm= 5430
.DW 21978 ; nAdc= 345, f= 91, upm= 5460
.DW 21858 ; nAdc= 346, f= 91,5, upm= 5490
.DW 21739 ; nAdc= 347, f= 92, upm= 5520
.DW 21622 ; nAdc= 348, f= 92,5, upm= 5550
.DW 21505 ; nAdc= 349, f= 93, upm= 5580
.DW 21390 ; nAdc= 350, f= 93,5, upm= 5610
.DW 21277 ; nAdc= 351, f= 94, upm= 5640
.DW 21164 ; nAdc= 352, f= 94,5, upm= 5670
.DW 21053 ; nAdc= 353, f= 95, upm= 5700
.DW 20942 ; nAdc= 354, f= 95,5, upm= 5730
.DW 20833 ; nAdc= 355, f= 96, upm= 5760
.DW 20725 ; nAdc= 356, f= 96,5, upm= 5790
.DW 20619 ; nAdc= 357, f= 97, upm= 5820
.DW 20513 ; nAdc= 358, f= 97,5, upm= 5850
.DW 20408 ; nAdc= 359, f= 98, upm= 5880
.DW 20305 ; nAdc= 360, f= 98,5, upm= 5910
.DW 20202 ; nAdc= 361, f= 99, upm= 5940
.DW 20101 ; nAdc= 362, f= 99,5, upm= 5970
.DW 20000 ; nAdc= 363, f= 100, upm= 6000
.DW 19048 ; nAdc= 364, f= 105, upm= 6300
.DW 18182 ; nAdc= 365, f= 110, upm= 6600
.DW 17391 ; nAdc= 366, f= 115, upm= 6900
.DW 16667 ; nAdc= 367, f= 120, upm= 7200
.DW 16000 ; nAdc= 368, f= 125, upm= 7500
.DW 15385 ; nAdc= 369, f= 130, upm= 7800
.DW 14815 ; nAdc= 370, f= 135, upm= 8100
.DW 14286 ; nAdc= 371, f= 140, upm= 8400
.DW 13793 ; nAdc= 372, f= 145, upm= 8700
.DW 13333 ; nAdc= 373, f= 150, upm= 9000
.DW 12903 ; nAdc= 374, f= 155, upm= 9300
.DW 12500 ; nAdc= 375, f= 160, upm= 9600
.DW 12121 ; nAdc= 376, f= 165, upm= 9900
.DW 11765 ; nAdc= 377, f= 170, upm= 10200
.DW 11429 ; nAdc= 378, f= 174,99, upm= 10500
.DW 11111 ; nAdc= 379, f= 180, upm= 10800
.DW 10811 ; nAdc= 380, f= 185, upm= 11100
.DW 10526 ; nAdc= 381, f= 190,01, upm= 11400
.DW 10256 ; nAdc= 382, f= 195,01, upm= 11700
.DW 10000 ; nAdc= 383, f= 200, upm= 12000
.DW 9756 ; nAdc= 384, f= 205, upm= 12300
.DW 9524 ; nAdc= 385, f= 210, upm= 12600
.DW 9302 ; nAdc= 386, f= 215,01, upm= 12900
.DW 9091 ; nAdc= 387, f= 220, upm= 13200
.DW 8889 ; nAdc= 388, f= 225, upm= 13500
.DW 8696 ; nAdc= 389, f= 229,99, upm= 13799
.DW 8511 ; nAdc= 390, f= 234,99, upm= 14099
.DW 8333 ; nAdc= 391, f= 240,01, upm= 14401
.DW 65306 ; nAdc= 392, f= 245, upm= 14700
.DW 64000 ; nAdc= 393, f= 250, upm= 15000
.DW 62745 ; nAdc= 394, f= 255, upm= 15300
.DW 61538 ; nAdc= 395, f= 260, upm= 15600
.DW 60377 ; nAdc= 396, f= 265, upm= 15900
.DW 59259 ; nAdc= 397, f= 270, upm= 16200
.DW 58182 ; nAdc= 398, f= 275, upm= 16500
.DW 57143 ; nAdc= 399, f= 280, upm= 16800
.DW 56140 ; nAdc= 400, f= 285, upm= 17100
.DW 55172 ; nAdc= 401, f= 290, upm= 17400
.DW 54237 ; nAdc= 402, f= 295, upm= 17700
.DW 53333 ; nAdc= 403, f= 300, upm= 18000
.DW 52459 ; nAdc= 404, f= 305, upm= 18300
.DW 51613 ; nAdc= 405, f= 310, upm= 18600
.DW 50794 ; nAdc= 406, f= 315, upm= 18900
.DW 50000 ; nAdc= 407, f= 320, upm= 19200
.DW 49231 ; nAdc= 408, f= 325, upm= 19500
.DW 48485 ; nAdc= 409, f= 330, upm= 19800
.DW 47761 ; nAdc= 410, f= 335, upm= 20100
.DW 47059 ; nAdc= 411, f= 340, upm= 20400
.DW 46377 ; nAdc= 412, f= 345, upm= 20700
.DW 45714 ; nAdc= 413, f= 350, upm= 21000
.DW 45070 ; nAdc= 414, f= 355, upm= 21300
.DW 44444 ; nAdc= 415, f= 360, upm= 21600
.DW 43836 ; nAdc= 416, f= 365, upm= 21900
.DW 43243 ; nAdc= 417, f= 370, upm= 22200
.DW 42667 ; nAdc= 418, f= 375, upm= 22500
.DW 42105 ; nAdc= 419, f= 380, upm= 22800
.DW 41558 ; nAdc= 420, f= 385, upm= 23100
.DW 41026 ; nAdc= 421, f= 390, upm= 23400
.DW 40506 ; nAdc= 422, f= 395, upm= 23700
.DW 40000 ; nAdc= 423, f= 400, upm= 24000
.DW 39506 ; nAdc= 424, f= 405, upm= 24300
.DW 39024 ; nAdc= 425, f= 410, upm= 24600
.DW 38554 ; nAdc= 426, f= 415, upm= 24900
.DW 38095 ; nAdc= 427, f= 420, upm= 25200
.DW 37647 ; nAdc= 428, f= 425, upm= 25500
.DW 37209 ; nAdc= 429, f= 430, upm= 25800
.DW 36782 ; nAdc= 430, f= 435, upm= 26100
.DW 36364 ; nAdc= 431, f= 440, upm= 26400
.DW 35955 ; nAdc= 432, f= 445, upm= 26700
.DW 35556 ; nAdc= 433, f= 449,99, upm= 27000
.DW 35165 ; nAdc= 434, f= 455, upm= 27300
.DW 34783 ; nAdc= 435, f= 459,99, upm= 27600
.DW 34409 ; nAdc= 436, f= 464,99, upm= 27900
.DW 34043 ; nAdc= 437, f= 469,99, upm= 28200
.DW 33684 ; nAdc= 438, f= 475, upm= 28500
.DW 33333 ; nAdc= 439, f= 480, upm= 28800
.DW 32990 ; nAdc= 440, f= 485, upm= 29100
.DW 32653 ; nAdc= 441, f= 490, upm= 29400
.DW 32323 ; nAdc= 442, f= 495, upm= 29700
.DW 32000 ; nAdc= 443, f= 500, upm= 30000
.DW 31683 ; nAdc= 444, f= 505, upm= 30300
.DW 31373 ; nAdc= 445, f= 509,99, upm= 30600
.DW 31068 ; nAdc= 446, f= 515, upm= 30900
.DW 30769 ; nAdc= 447, f= 520, upm= 31200
.DW 30476 ; nAdc= 448, f= 525, upm= 31500
.DW 30189 ; nAdc= 449, f= 529,99, upm= 31800
.DW 29907 ; nAdc= 450, f= 534,99, upm= 32100
.DW 29630 ; nAdc= 451, f= 539,99, upm= 32400
.DW 29358 ; nAdc= 452, f= 545, upm= 32700
.DW 29091 ; nAdc= 453, f= 550, upm= 33000
.DW 28829 ; nAdc= 454, f= 555, upm= 33300
.DW 28571 ; nAdc= 455, f= 560,01, upm= 33601
.DW 28319 ; nAdc= 456, f= 564,99, upm= 33900
.DW 28070 ; nAdc= 457, f= 570, upm= 34200
.DW 27826 ; nAdc= 458, f= 575, upm= 34500
.DW 27586 ; nAdc= 459, f= 580, upm= 34800
.DW 27350 ; nAdc= 460, f= 585,01, upm= 35101
.DW 27119 ; nAdc= 461, f= 589,99, upm= 35400
.DW 26891 ; nAdc= 462, f= 594,99, upm= 35700
.DW 26667 ; nAdc= 463, f= 599,99, upm= 36000
.DW 26446 ; nAdc= 464, f= 605,01, upm= 36300
.DW 26230 ; nAdc= 465, f= 609,99, upm= 36599
.DW 26016 ; nAdc= 466, f= 615,01, upm= 36900
.DW 25806 ; nAdc= 467, f= 620,01, upm= 37201
.DW 25600 ; nAdc= 468, f= 625, upm= 37500
.DW 25397 ; nAdc= 469, f= 630, upm= 37800
.DW 25197 ; nAdc= 470, f= 635, upm= 38100
.DW 25000 ; nAdc= 471, f= 640, upm= 38400
.DW 24806 ; nAdc= 472, f= 645,01, upm= 38700
.DW 24615 ; nAdc= 473, f= 650,01, upm= 39001
.DW 24427 ; nAdc= 474, f= 655,01, upm= 39301
.DW 24242 ; nAdc= 475, f= 660,01, upm= 39601
.DW 24060 ; nAdc= 476, f= 665, upm= 39900
.DW 23881 ; nAdc= 477, f= 669,99, upm= 40199
.DW 23704 ; nAdc= 478, f= 674,99, upm= 40499
.DW 23529 ; nAdc= 479, f= 680,01, upm= 40801
.DW 23358 ; nAdc= 480, f= 684,99, upm= 41099
.DW 23188 ; nAdc= 481, f= 690,01, upm= 41401
.DW 23022 ; nAdc= 482, f= 694,99, upm= 41699
.DW 22857 ; nAdc= 483, f= 700, upm= 42000
.DW 22695 ; nAdc= 484, f= 705, upm= 42300
.DW 22535 ; nAdc= 485, f= 710,01, upm= 42600
.DW 22378 ; nAdc= 486, f= 714,99, upm= 42899
.DW 22222 ; nAdc= 487, f= 720,01, upm= 43200
.DW 22069 ; nAdc= 488, f= 725, upm= 43500
.DW 21918 ; nAdc= 489, f= 729,99, upm= 43800
.DW 21769 ; nAdc= 490, f= 734,99, upm= 44099
.DW 21622 ; nAdc= 491, f= 739,99, upm= 44399
.DW 21477 ; nAdc= 492, f= 744,98, upm= 44699
.DW 21333 ; nAdc= 493, f= 750,01, upm= 45001
.DW 21192 ; nAdc= 494, f= 755, upm= 45300
.DW 21053 ; nAdc= 495, f= 759,99, upm= 45599
.DW 20915 ; nAdc= 496, f= 765, upm= 45900
.DW 20779 ; nAdc= 497, f= 770,01, upm= 46200
.DW 20645 ; nAdc= 498, f= 775,01, upm= 46500
.DW 20513 ; nAdc= 499, f= 779,99, upm= 46800
.DW 20382 ; nAdc= 500, f= 785,01, upm= 47100
.DW 20253 ; nAdc= 501, f= 790,01, upm= 47400
.DW 20126 ; nAdc= 502, f= 794,99, upm= 47699
.DW 20000 ; nAdc= 503, f= 800, upm= 48000
.DW 19876 ; nAdc= 504, f= 804,99, upm= 48299
.DW 19753 ; nAdc= 505, f= 810, upm= 48600
.DW 19632 ; nAdc= 506, f= 815, upm= 48900
.DW 19512 ; nAdc= 507, f= 820,01, upm= 49200
.DW 19394 ; nAdc= 508, f= 825, upm= 49500
.DW 19277 ; nAdc= 509, f= 830, upm= 49800
.DW 19162 ; nAdc= 510, f= 834,99, upm= 50099
.DW 19048 ; nAdc= 511, f= 839,98, upm= 50399
.DW 18935 ; nAdc= 512, f= 845, upm= 50700
.DW 18824 ; nAdc= 513, f= 849,98, upm= 50999
.DW 18713 ; nAdc= 514, f= 855,02, upm= 51301
.DW 18605 ; nAdc= 515, f= 859,98, upm= 51599
.DW 18497 ; nAdc= 516, f= 865,01, upm= 51900
.DW 18391 ; nAdc= 517, f= 869,99, upm= 52199
.DW 18286 ; nAdc= 518, f= 874,99, upm= 52499
.DW 18182 ; nAdc= 519, f= 879,99, upm= 52799
.DW 18079 ; nAdc= 520, f= 885, upm= 53100
.DW 17978 ; nAdc= 521, f= 889,98, upm= 53399
.DW 17877 ; nAdc= 522, f= 895, upm= 53700
.DW 17778 ; nAdc= 523, f= 899,99, upm= 53999
.DW 17680 ; nAdc= 524, f= 904,98, upm= 54299
.DW 17582 ; nAdc= 525, f= 910,02, upm= 54601
.DW 17486 ; nAdc= 526, f= 915,02, upm= 54901
.DW 17391 ; nAdc= 527, f= 920,02, upm= 55201
.DW 17297 ; nAdc= 528, f= 925,02, upm= 55501
.DW 17204 ; nAdc= 529, f= 930,02, upm= 55801
.DW 17112 ; nAdc= 530, f= 935,02, upm= 56101
.DW 17021 ; nAdc= 531, f= 940,02, upm= 56401
.DW 16931 ; nAdc= 532, f= 945,01, upm= 56701
.DW 16842 ; nAdc= 533, f= 950,01, upm= 57000
.DW 16754 ; nAdc= 534, f= 955, upm= 57300
.DW 16667 ; nAdc= 535, f= 959,98, upm= 57599
.DW 16580 ; nAdc= 536, f= 965,02, upm= 57901
.DW 16495 ; nAdc= 537, f= 969,99, upm= 58199
.DW 16410 ; nAdc= 538, f= 975,02, upm= 58501
.DW 16327 ; nAdc= 539, f= 979,97, upm= 58798
.DW 16244 ; nAdc= 540, f= 984,98, upm= 59099
.DW 16162 ; nAdc= 541, f= 989,98, upm= 59399
.DW 16080 ; nAdc= 542, f= 995,02, upm= 59701
.DW 16000 ; nAdc= 543, f= 1000, upm= 60000
.DW 15238 ; nAdc= 544, f= 1050,01
.DW 14545 ; nAdc= 545, f= 1100,03
.DW 13913 ; nAdc= 546, f= 1150
.DW 13333 ; nAdc= 547, f= 1200,03
.DW 12800 ; nAdc= 548, f= 1250
.DW 12308 ; nAdc= 549, f= 1299,97
.DW 11852 ; nAdc= 550, f= 1349,98
.DW 11429 ; nAdc= 551, f= 1399,95
.DW 11034 ; nAdc= 552, f= 1450,06
.DW 10667 ; nAdc= 553, f= 1499,95
.DW 10323 ; nAdc= 554, f= 1549,94
.DW 10000 ; nAdc= 555, f= 1600
.DW 9697 ; nAdc= 556, f= 1649,99
.DW 9412 ; nAdc= 557, f= 1699,96
.DW 9143 ; nAdc= 558, f= 1749,97
.DW 8889 ; nAdc= 559, f= 1799,98
.DW 8649 ; nAdc= 560, f= 1849,92
.DW 8421 ; nAdc= 561, f= 1900,01
.DW 8205 ; nAdc= 562, f= 1950,03
.DW 8000 ; nAdc= 563, f= 2000
.DW 7805 ; nAdc= 564, f= 2049,97
.DW 7619 ; nAdc= 565, f= 2100,01
.DW 7442 ; nAdc= 566, f= 2149,96
.DW 7273 ; nAdc= 567, f= 2199,92
.DW 7111 ; nAdc= 568, f= 2250,04
.DW 6957 ; nAdc= 569, f= 2299,84
.DW 6809 ; nAdc= 570, f= 2349,83
.DW 6667 ; nAdc= 571, f= 2399,88
.DW 6531 ; nAdc= 572, f= 2449,85
.DW 6400 ; nAdc= 573, f= 2500
.DW 6275 ; nAdc= 574, f= 2549,8
.DW 6154 ; nAdc= 575, f= 2599,94
.DW 6038 ; nAdc= 576, f= 2649,88
.DW 5926 ; nAdc= 577, f= 2699,97
.DW 5818 ; nAdc= 578, f= 2750,09
.DW 5714 ; nAdc= 579, f= 2800,14
.DW 5614 ; nAdc= 580, f= 2850,02
.DW 5517 ; nAdc= 581, f= 2900,13
.DW 5424 ; nAdc= 582, f= 2949,85
.DW 5333 ; nAdc= 583, f= 3000,19
.DW 5246 ; nAdc= 584, f= 3049,94
.DW 5161 ; nAdc= 585, f= 3100,17
.DW 5079 ; nAdc= 586, f= 3150,23
.DW 5000 ; nAdc= 587, f= 3200
.DW 4923 ; nAdc= 588, f= 3250,05
.DW 4848 ; nAdc= 589, f= 3300,33
.DW 4776 ; nAdc= 590, f= 3350,08
.DW 4706 ; nAdc= 591, f= 3399,92
.DW 4638 ; nAdc= 592, f= 3449,76
.DW 4571 ; nAdc= 593, f= 3500,33
.DW 4507 ; nAdc= 594, f= 3550,03
.DW 4444 ; nAdc= 595, f= 3600,36
.DW 4384 ; nAdc= 596, f= 3649,64
.DW 4324 ; nAdc= 597, f= 3700,28
.DW 4267 ; nAdc= 598, f= 3749,71
.DW 4211 ; nAdc= 599, f= 3799,57
.DW 4156 ; nAdc= 600, f= 3849,86
.DW 4103 ; nAdc= 601, f= 3899,59
.DW 4051 ; nAdc= 602, f= 3949,64
.DW 4000 ; nAdc= 603, f= 4000
.DW 3951 ; nAdc= 604, f= 4049,61
.DW 3902 ; nAdc= 605, f= 4100,46
.DW 3855 ; nAdc= 606, f= 4150,45
.DW 3810 ; nAdc= 607, f= 4199,48
.DW 3765 ; nAdc= 608, f= 4249,67
.DW 3721 ; nAdc= 609, f= 4299,92
.DW 3678 ; nAdc= 610, f= 4350,19
.DW 3636 ; nAdc= 611, f= 4400,44
.DW 3596 ; nAdc= 612, f= 4449,39
.DW 3556 ; nAdc= 613, f= 4499,44
.DW 3516 ; nAdc= 614, f= 4550,63
.DW 3478 ; nAdc= 615, f= 4600,35
.DW 3441 ; nAdc= 616, f= 4649,81
.DW 3404 ; nAdc= 617, f= 4700,35
.DW 3368 ; nAdc= 618, f= 4750,59
.DW 3333 ; nAdc= 619, f= 4800,48
.DW 3299 ; nAdc= 620, f= 4849,95
.DW 3265 ; nAdc= 621, f= 4900,46
.DW 3232 ; nAdc= 622, f= 4950,5
.DW 3200 ; nAdc= 623, f= 5000
.DW 3168 ; nAdc= 624, f= 5050,51
.DW 3137 ; nAdc= 625, f= 5100,41
.DW 3107 ; nAdc= 626, f= 5149,66
.DW 3077 ; nAdc= 627, f= 5199,87
.DW 3048 ; nAdc= 628, f= 5249,34
.DW 3019 ; nAdc= 629, f= 5299,77
.DW 2991 ; nAdc= 630, f= 5349,38
.DW 2963 ; nAdc= 631, f= 5399,93
.DW 2936 ; nAdc= 632, f= 5449,59
.DW 2909 ; nAdc= 633, f= 5500,17
.DW 2883 ; nAdc= 634, f= 5549,77
.DW 2857 ; nAdc= 635, f= 5600,28
.DW 2832 ; nAdc= 636, f= 5649,72
.DW 2807 ; nAdc= 637, f= 5700,04
.DW 2783 ; nAdc= 638, f= 5749,19
.DW 2759 ; nAdc= 639, f= 5799,2
.DW 2735 ; nAdc= 640, f= 5850,09
.DW 2712 ; nAdc= 641, f= 5899,71
.DW 2689 ; nAdc= 642, f= 5950,17
.DW 2667 ; nAdc= 643, f= 5999,25
.DW 2645 ; nAdc= 644, f= 6049,15
.DW 2623 ; nAdc= 645, f= 6099,89
.DW 2602 ; nAdc= 646, f= 6149,12
.DW 2581 ; nAdc= 647, f= 6199,15
.DW 2560 ; nAdc= 648, f= 6250
.DW 2540 ; nAdc= 649, f= 6299,21
.DW 2520 ; nAdc= 650, f= 6349,21
.DW 2500 ; nAdc= 651, f= 6400
.DW 2481 ; nAdc= 652, f= 6449,01
.DW 2462 ; nAdc= 653, f= 6498,78
.DW 2443 ; nAdc= 654, f= 6549,32
.DW 2424 ; nAdc= 655, f= 6600,66
.DW 2406 ; nAdc= 656, f= 6650,04
.DW 2388 ; nAdc= 657, f= 6700,17
.DW 2370 ; nAdc= 658, f= 6751,05
.DW 2353 ; nAdc= 659, f= 6799,83
.DW 2336 ; nAdc= 660, f= 6849,32
.DW 2319 ; nAdc= 661, f= 6899,53
.DW 2302 ; nAdc= 662, f= 6950,48
.DW 2286 ; nAdc= 663, f= 6999,13
.DW 2270 ; nAdc= 664, f= 7048,46
.DW 2254 ; nAdc= 665, f= 7098,49
.DW 2238 ; nAdc= 666, f= 7149,24
.DW 2222 ; nAdc= 667, f= 7200,72
.DW 2207 ; nAdc= 668, f= 7249,66
.DW 2192 ; nAdc= 669, f= 7299,27
.DW 2177 ; nAdc= 670, f= 7349,56
.DW 2162 ; nAdc= 671, f= 7400,56
.DW 2148 ; nAdc= 672, f= 7448,79
.DW 2133 ; nAdc= 673, f= 7501,17
.DW 2119 ; nAdc= 674, f= 7550,73
.DW 2105 ; nAdc= 675, f= 7600,95
.DW 2092 ; nAdc= 676, f= 7648,18
.DW 2078 ; nAdc= 677, f= 7699,71
.DW 2065 ; nAdc= 678, f= 7748,18
.DW 2051 ; nAdc= 679, f= 7801,07
.DW 2038 ; nAdc= 680, f= 7850,83
.DW 2025 ; nAdc= 681, f= 7901,23
.DW 2013 ; nAdc= 682, f= 7948,34
.DW 2000 ; nAdc= 683, f= 8000
.DW 1988 ; nAdc= 684, f= 8048,29
.DW 1975 ; nAdc= 685, f= 8101,27
.DW 1963 ; nAdc= 686, f= 8150,79
.DW 1951 ; nAdc= 687, f= 8200,92
.DW 1939 ; nAdc= 688, f= 8251,68
.DW 1928 ; nAdc= 689, f= 8298,76
.DW 1916 ; nAdc= 690, f= 8350,73
.DW 1905 ; nAdc= 691, f= 8398,95
.DW 1893 ; nAdc= 692, f= 8452,19
.DW 1882 ; nAdc= 693, f= 8501,59
.DW 1871 ; nAdc= 694, f= 8551,58
.DW 1860 ; nAdc= 695, f= 8602,15
.DW 1850 ; nAdc= 696, f= 8648,65
.DW 1839 ; nAdc= 697, f= 8700,38
.DW 1829 ; nAdc= 698, f= 8747,95
.DW 1818 ; nAdc= 699, f= 8800,88
.DW 1808 ; nAdc= 700, f= 8849,56
.DW 1798 ; nAdc= 701, f= 8898,78
.DW 1788 ; nAdc= 702, f= 8948,55
.DW 1778 ; nAdc= 703, f= 8998,88
.DW 1768 ; nAdc= 704, f= 9049,77
.DW 1758 ; nAdc= 705, f= 9101,25
.DW 1749 ; nAdc= 706, f= 9148,08
.DW 1739 ; nAdc= 707, f= 9200,69
.DW 1730 ; nAdc= 708, f= 9248,55
.DW 1720 ; nAdc= 709, f= 9302,33
.DW 1711 ; nAdc= 710, f= 9351,26
.DW 1702 ; nAdc= 711, f= 9400,71
.DW 1693 ; nAdc= 712, f= 9450,68
.DW 1684 ; nAdc= 713, f= 9501,19
.DW 1675 ; nAdc= 714, f= 9552,24
.DW 1667 ; nAdc= 715, f= 9598,08
.DW 1658 ; nAdc= 716, f= 9650,18
.DW 1649 ; nAdc= 717, f= 9702,85
.DW 1641 ; nAdc= 718, f= 9750,15
.DW 1633 ; nAdc= 719, f= 9797,92
.DW 1624 ; nAdc= 720, f= 9852,22
.DW 1616 ; nAdc= 721, f= 9900,99
.DW 1608 ; nAdc= 722, f= 9950,25
.DW 1600 ; nAdc= 723, f= 10000
.DW 1524 ; nAdc= 724, f= 10498,69
.DW 1455 ; nAdc= 725, f= 10996,56
.DW 1391 ; nAdc= 726, f= 11502,52
.DW 1333 ; nAdc= 727, f= 12003
.DW 1280 ; nAdc= 728, f= 12500
.DW 1231 ; nAdc= 729, f= 12997,56
.DW 1185 ; nAdc= 730, f= 13502,11
.DW 1143 ; nAdc= 731, f= 13998,25
.DW 1103 ; nAdc= 732, f= 14505,89
.DW 1067 ; nAdc= 733, f= 14995,31
.DW 1032 ; nAdc= 734, f= 15503,88
.DW 1000 ; nAdc= 735, f= 16000
.DW 970 ; nAdc= 736, f= 16494,85
.DW 941 ; nAdc= 737, f= 17003,19
.DW 914 ; nAdc= 738, f= 17505,47
.DW 889 ; nAdc= 739, f= 17997,75
.DW 865 ; nAdc= 740, f= 18497,11
.DW 842 ; nAdc= 741, f= 19002,38
.DW 821 ; nAdc= 742, f= 19488,43
.DW 800 ; nAdc= 743, f= 20000
.DW 780 ; nAdc= 744, f= 20512,82
.DW 762 ; nAdc= 745, f= 20997,38
.DW 744 ; nAdc= 746, f= 21505,38
.DW 727 ; nAdc= 747, f= 22008,25
.DW 711 ; nAdc= 748, f= 22503,52
.DW 696 ; nAdc= 749, f= 22988,51
.DW 681 ; nAdc= 750, f= 23494,86
.DW 667 ; nAdc= 751, f= 23988,01
.DW 653 ; nAdc= 752, f= 24502,3
.DW 640 ; nAdc= 753, f= 25000
.DW 627 ; nAdc= 754, f= 25518,34
.DW 615 ; nAdc= 755, f= 26016,26
.DW 604 ; nAdc= 756, f= 26490,07
.DW 593 ; nAdc= 757, f= 26981,45
.DW 582 ; nAdc= 758, f= 27491,41
.DW 571 ; nAdc= 759, f= 28021,02
.DW 561 ; nAdc= 760, f= 28520,5
.DW 552 ; nAdc= 761, f= 28985,51
.DW 542 ; nAdc= 762, f= 29520,3
.DW 533 ; nAdc= 763, f= 30018,76
.DW 525 ; nAdc= 764, f= 30476,19
.DW 516 ; nAdc= 765, f= 31007,75
.DW 508 ; nAdc= 766, f= 31496,06
.DW 500 ; nAdc= 767, f= 32000
.DW 492 ; nAdc= 768, f= 32520,33
.DW 485 ; nAdc= 769, f= 32989,69
.DW 478 ; nAdc= 770, f= 33472,8
.DW 471 ; nAdc= 771, f= 33970,28
.DW 464 ; nAdc= 772, f= 34482,76
.DW 457 ; nAdc= 773, f= 35010,94
.DW 451 ; nAdc= 774, f= 35476,72
.DW 444 ; nAdc= 775, f= 36036,04
.DW 438 ; nAdc= 776, f= 36529,68
.DW 432 ; nAdc= 777, f= 37037,04
.DW 427 ; nAdc= 778, f= 37470,73
.DW 421 ; nAdc= 779, f= 38004,75
.DW 416 ; nAdc= 780, f= 38461,54
.DW 410 ; nAdc= 781, f= 39024,39
.DW 405 ; nAdc= 782, f= 39506,17
.DW 400 ; nAdc= 783, f= 40000
.DW 395 ; nAdc= 784, f= 40506,33
.DW 390 ; nAdc= 785, f= 41025,64
.DW 386 ; nAdc= 786, f= 41450,78
.DW 381 ; nAdc= 787, f= 41994,75
.DW 376 ; nAdc= 788, f= 42553,19
.DW 372 ; nAdc= 789, f= 43010,75
.DW 368 ; nAdc= 790, f= 43478,26
.DW 364 ; nAdc= 791, f= 43956,04
.DW 360 ; nAdc= 792, f= 44444,44
.DW 356 ; nAdc= 793, f= 44943,82
.DW 352 ; nAdc= 794, f= 45454,55
.DW 348 ; nAdc= 795, f= 45977,01
.DW 344 ; nAdc= 796, f= 46511,63
.DW 340 ; nAdc= 797, f= 47058,82
.DW 337 ; nAdc= 798, f= 47477,74
.DW 333 ; nAdc= 799, f= 48048,05
.DW 330 ; nAdc= 800, f= 48484,85
.DW 327 ; nAdc= 801, f= 48929,66
.DW 323 ; nAdc= 802, f= 49535,6
.DW 320 ; nAdc= 803, f= 50000
.DW 317 ; nAdc= 804, f= 50473,19
.DW 314 ; nAdc= 805, f= 50955,41
.DW 311 ; nAdc= 806, f= 51446,95
.DW 308 ; nAdc= 807, f= 51948,05
.DW 305 ; nAdc= 808, f= 52459,02
.DW 302 ; nAdc= 809, f= 52980,13
.DW 299 ; nAdc= 810, f= 53511,71
.DW 296 ; nAdc= 811, f= 54054,05
.DW 294 ; nAdc= 812, f= 54421,77
.DW 291 ; nAdc= 813, f= 54982,82
.DW 288 ; nAdc= 814, f= 55555,56
.DW 286 ; nAdc= 815, f= 55944,06
.DW 283 ; nAdc= 816, f= 56537,1
.DW 281 ; nAdc= 817, f= 56939,5
.DW 278 ; nAdc= 818, f= 57553,96
.DW 276 ; nAdc= 819, f= 57971,01
.DW 274 ; nAdc= 820, f= 58394,16
.DW 271 ; nAdc= 821, f= 59040,59
.DW 269 ; nAdc= 822, f= 59479,55
.DW 267 ; nAdc= 823, f= 59925,09
.DW 264 ; nAdc= 824, f= 60606,06
.DW 262 ; nAdc= 825, f= 61068,7
.DW 260 ; nAdc= 826, f= 61538,46
.DW 258 ; nAdc= 827, f= 62015,5
.DW 256 ; nAdc= 828, f= 62500
.DW 254 ; nAdc= 829, f= 62992,13
.DW 252 ; nAdc= 830, f= 63492,06
.DW 250 ; nAdc= 831, f= 64000
.DW 248 ; nAdc= 832, f= 64516,13

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8_v1_freqtab.html (1 of 2)1/20/2009 7:39:25 PM


Rechteckgenerator ATmega8 - Quellcode Frequenztabelle

.DW 246 ; nAdc= 833, f= 65040,65


.DW 244 ; nAdc= 834, f= 65573,77
.DW 242 ; nAdc= 835, f= 66115,7
.DW 241 ; nAdc= 836, f= 66390,04
.DW 239 ; nAdc= 837, f= 66945,61
.DW 237 ; nAdc= 838, f= 67510,55
.DW 235 ; nAdc= 839, f= 68085,11
.DW 234 ; nAdc= 840, f= 68376,07
.DW 232 ; nAdc= 841, f= 68965,52
.DW 230 ; nAdc= 842, f= 69565,22
.DW 229 ; nAdc= 843, f= 69869
.DW 227 ; nAdc= 844, f= 70484,58
.DW 225 ; nAdc= 845, f= 71111,11
.DW 224 ; nAdc= 846, f= 71428,57
.DW 222 ; nAdc= 847, f= 72072,07
.DW 221 ; nAdc= 848, f= 72398,19
.DW 219 ; nAdc= 849, f= 73059,36
.DW 218 ; nAdc= 850, f= 73394,5
.DW 216 ; nAdc= 851, f= 74074,07
.DW 215 ; nAdc= 852, f= 74418,6
.DW 213 ; nAdc= 853, f= 75117,37
.DW 212 ; nAdc= 854, f= 75471,7
.DW 211 ; nAdc= 855, f= 75829,38
.DW 209 ; nAdc= 856, f= 76555,02
.DW 208 ; nAdc= 857, f= 76923,08
.DW 206 ; nAdc= 858, f= 77669,9
.DW 205 ; nAdc= 859, f= 78048,78
.DW 204 ; nAdc= 860, f= 78431,37
.DW 203 ; nAdc= 861, f= 78817,73
.DW 201 ; nAdc= 862, f= 79601,99
.DW 200 ; nAdc= 863, f= 80000
.DW 199 ; nAdc= 864, f= 80402,01
.DW 198 ; nAdc= 865, f= 80808,08
.DW 196 ; nAdc= 866, f= 81632,65
.DW 195 ; nAdc= 867, f= 82051,28
.DW 194 ; nAdc= 868, f= 82474,23
.DW 193 ; nAdc= 869, f= 82901,55
.DW 192 ; nAdc= 870, f= 83333,33
.DW 190 ; nAdc= 871, f= 84210,53
.DW 189 ; nAdc= 872, f= 84656,08
.DW 188 ; nAdc= 873, f= 85106,38
.DW 187 ; nAdc= 874, f= 85561,5
.DW 186 ; nAdc= 875, f= 86021,51
.DW 185 ; nAdc= 876, f= 86486,49
.DW 184 ; nAdc= 877, f= 86956,52
.DW 183 ; nAdc= 878, f= 87431,69
.DW 182 ; nAdc= 879, f= 87912,09
.DW 181 ; nAdc= 880, f= 88397,79
.DW 180 ; nAdc= 881, f= 88888,89
.DW 179 ; nAdc= 882, f= 89385,47
.DW 178 ; nAdc= 883, f= 89887,64
.DW 177 ; nAdc= 884, f= 90395,48
.DW 176 ; nAdc= 885, f= 90909,09
.DW 175 ; nAdc= 886, f= 91428,57
.DW 174 ; nAdc= 887, f= 91954,02
.DW 173 ; nAdc= 888, f= 92485,55
.DW 172 ; nAdc= 889, f= 93023,26
.DW 171 ; nAdc= 890, f= 93567,25
.DW 170 ; nAdc= 891, f= 94117,65
.DW 169 ; nAdc= 892, f= 94674,56
.DW 168 ; nAdc= 893, f= 95238,1
.DW 168 ; nAdc= 894, f= 95238,1
.DW 167 ; nAdc= 895, f= 95808,38
.DW 166 ; nAdc= 896, f= 96385,54
.DW 165 ; nAdc= 897, f= 96969,7
.DW 164 ; nAdc= 898, f= 97560,98
.DW 163 ; nAdc= 899, f= 98159,51
.DW 162 ; nAdc= 900, f= 98765,43
.DW 162 ; nAdc= 901, f= 98765,43
.DW 161 ; nAdc= 902, f= 99378,88
.DW 160 ; nAdc= 903, f= 100000
.DW 152 ; nAdc= 904, f= 105263,16
.DW 145 ; nAdc= 905, f= 110344,83
.DW 139 ; nAdc= 906, f= 115107,91
.DW 133 ; nAdc= 907, f= 120300,75
.DW 128 ; nAdc= 908, f= 125000
.DW 123 ; nAdc= 909, f= 130081,3
.DW 119 ; nAdc= 910, f= 134453,78
.DW 116 ; nAdc= 911, f= 137931,03
.DW 113 ; nAdc= 912, f= 141592,92
.DW 112 ; nAdc= 913, f= 142857,14
.DW 111 ; nAdc= 914, f= 144144,14
.DW 110 ; nAdc= 915, f= 145454,55
.DW 109 ; nAdc= 916, f= 146788,99
.DW 108 ; nAdc= 917, f= 148148,15
.DW 107 ; nAdc= 918, f= 149532,71
.DW 106 ; nAdc= 919, f= 150943,4
.DW 105 ; nAdc= 920, f= 152380,95
.DW 104 ; nAdc= 921, f= 153846,15
.DW 103 ; nAdc= 922, f= 155339,81
.DW 102 ; nAdc= 923, f= 156862,75
.DW 101 ; nAdc= 924, f= 158415,84
.DW 100 ; nAdc= 925, f= 160000
.DW 99 ; nAdc= 926, f= 161616,16
.DW 98 ; nAdc= 927, f= 163265,31
.DW 97 ; nAdc= 928, f= 164948,45
.DW 96 ; nAdc= 929, f= 166666,67
.DW 95 ; nAdc= 930, f= 168421,05
.DW 94 ; nAdc= 931, f= 170212,77
.DW 93 ; nAdc= 932, f= 172043,01
.DW 92 ; nAdc= 933, f= 173913,04
.DW 91 ; nAdc= 934, f= 175824,18
.DW 90 ; nAdc= 935, f= 177777,78
.DW 89 ; nAdc= 936, f= 179775,28
.DW 88 ; nAdc= 937, f= 181818,18
.DW 87 ; nAdc= 938, f= 183908,05
.DW 86 ; nAdc= 939, f= 186046,51
.DW 85 ; nAdc= 940, f= 188235,29
.DW 84 ; nAdc= 941, f= 190476,19
.DW 83 ; nAdc= 942, f= 192771,08
.DW 82 ; nAdc= 943, f= 195121,95
.DW 81 ; nAdc= 944, f= 197530,86
.DW 80 ; nAdc= 945, f= 200000
.DW 79 ; nAdc= 946, f= 202531,65
.DW 78 ; nAdc= 947, f= 205128,21
.DW 77 ; nAdc= 948, f= 207792,21
.DW 76 ; nAdc= 949, f= 210526,32
.DW 75 ; nAdc= 950, f= 213333,33
.DW 74 ; nAdc= 951, f= 216216,22
.DW 73 ; nAdc= 952, f= 219178,08
.DW 72 ; nAdc= 953, f= 222222,22
.DW 71 ; nAdc= 954, f= 225352,11
.DW 70 ; nAdc= 955, f= 228571,43
.DW 69 ; nAdc= 956, f= 231884,06
.DW 68 ; nAdc= 957, f= 235294,12
.DW 67 ; nAdc= 958, f= 238805,97
.DW 66 ; nAdc= 959, f= 242424,24
.DW 65 ; nAdc= 960, f= 246153,85
.DW 64 ; nAdc= 961, f= 250000
.DW 63 ; nAdc= 962, f= 253968,25
.DW 62 ; nAdc= 963, f= 258064,52
.DW 61 ; nAdc= 964, f= 262295,08
.DW 60 ; nAdc= 965, f= 266666,67
.DW 59 ; nAdc= 966, f= 271186,44
.DW 58 ; nAdc= 967, f= 275862,07
.DW 57 ; nAdc= 968, f= 280701,75
.DW 56 ; nAdc= 969, f= 285714,29
.DW 55 ; nAdc= 970, f= 290909,09
.DW 54 ; nAdc= 971, f= 296296,3
.DW 53 ; nAdc= 972, f= 301886,79
.DW 52 ; nAdc= 973, f= 307692,31
.DW 51 ; nAdc= 974, f= 313725,49
.DW 50 ; nAdc= 975, f= 320000
.DW 49 ; nAdc= 976, f= 326530,61
.DW 48 ; nAdc= 977, f= 333333,33
.DW 47 ; nAdc= 978, f= 340425,53
.DW 46 ; nAdc= 979, f= 347826,09
.DW 45 ; nAdc= 980, f= 355555,56
.DW 44 ; nAdc= 981, f= 363636,36
.DW 43 ; nAdc= 982, f= 372093,02
.DW 42 ; nAdc= 983, f= 380952,38
.DW 41 ; nAdc= 984, f= 390243,9
.DW 40 ; nAdc= 985, f= 400000
.DW 39 ; nAdc= 986, f= 410256,41
.DW 38 ; nAdc= 987, f= 421052,63
.DW 37 ; nAdc= 988, f= 432432,43
.DW 36 ; nAdc= 989, f= 444444,44
.DW 35 ; nAdc= 990, f= 457142,86
.DW 34 ; nAdc= 991, f= 470588,24
.DW 33 ; nAdc= 992, f= 484848,48
.DW 32 ; nAdc= 993, f= 500000
.DW 31 ; nAdc= 994, f= 516129,03
.DW 30 ; nAdc= 995, f= 533333,33
.DW 29 ; nAdc= 996, f= 551724,14
.DW 28 ; nAdc= 997, f= 571428,57
.DW 27 ; nAdc= 998, f= 592592,59
.DW 26 ; nAdc= 999, f= 615384,62
.DW 25 ; nAdc= 1000, f= 640000
.DW 24 ; nAdc= 1001, f= 666666,67
.DW 23 ; nAdc= 1002, f= 695652,17
.DW 22 ; nAdc= 1003, f= 727272,73
.DW 21 ; nAdc= 1004, f= 761904,76
.DW 20 ; nAdc= 1005, f= 800000
.DW 19 ; nAdc= 1006, f= 842105,26
.DW 18 ; nAdc= 1007, f= 888888,89
.DW 17 ; nAdc= 1008, f= 941176,47
.DW 16 ; nAdc= 1009, f= 1000000
.DW 15 ; nAdc= 1010, f= 1066666,67
.DW 14 ; nAdc= 1011, f= 1142857,14
.DW 13 ; nAdc= 1012, f= 1230769,23
.DW 12 ; nAdc= 1013, f= 1333333,33
.DW 11 ; nAdc= 1014, f= 1454545,45
.DW 10 ; nAdc= 1015, f= 1600000
.DW 9 ; nAdc= 1016, f= 1777777,78
.DW 8 ; nAdc= 1017, f= 2000000
.DW 7 ; nAdc= 1018, f= 2285714,29
.DW 6 ; nAdc= 1019, f= 2666666,67
.DW 5 ; nAdc= 1020, f= 3200000
.DW 4 ; nAdc= 1021, f= 4000000
.DW 3 ; nAdc= 1022, f= 5333333,33
.DW 2 ; nAdc= 1023, f= 8000000

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/rectgen_m8_v1_freqtab.html (2 of 2)1/20/2009 7:39:25 PM


40 MHz-Frequenzzähler mit ATmega8, Quellcode

Pfad: Home => AVR-Übersicht => Anwendungen => Frequenzzähler => Software

Software für den


Frequenzzähler

; ****************************************************
; * Frequenzzaehler, Drehzahlmesser und Voltmeter *
; * fuer ATmega8 bei 16 MHz Taktfrequenz (Quarzosz.) *
; * ohne Autorange, mit Vorteiler /1 oder /16 *
; * Version 0.3 (C)2009 by info@avr-asm-tutorial.net *
; ****************************************************
;
.INCLUDE "m8def.inc"
;
.EQU debug = 0
.EQU debugpulse = 0
;
; Switches for connected hardware
;
.EQU cDisplay = 1 ; LCD display connected
.EQU cDisplay8 = 0 ; displays 8 characters per line instead of 16
.EQU cDisplay2 = 1 ; two line LCD display connected
.EQU cUart = 1 ; Uart active
; attached prescaler on port C
.EQU pPresc = PORTC ; prescaler by 16 output attached to port C
.EQU pPrescD = DDRC ; data direction of prescaler
.EQU bPresc = 5 ; bit 5 enables prescaler by 16
;
; ================================================
; Other hardware depending stuff
; ================================================
;
.EQU cFreq = 16000000 ; Clock frequency processor in cycles/s
.IF cUart
.EQU cBaud = 9600 ; If Uart active, define Baudrate
.ENDIF
.EQU bLcdE = 5 ; LCD E port bit on Port B
.EQU bLcdRs = 4 ; Lcd RS port bit on Port B
;
; ================================================
; Constants for voltage measurement
; ================================================
;
; Resistor network as pre-divider for the ADC
; --------------------------------------
; R1 R2(k) Meas Accur. MaxVoltage
; kOhm kOhm Volt mV/dig Volt
; --------------------------------------
; 1000 1000 5,12 5 10
; 1000 820 5,68 6 11
; 1000 680 6,32 6 12
; 1000 560 7,13 7 14
; 1000 470 8,01 8 15
; 1000 330 10,32 10 20
; 1000 270 12,04 12 23
; 1000 220 14,20 14 27
; 1000 180 16,78 16 32
; 1000 150 19,63 19 38
; 1000 120 23,98 23 46
; 1000 100 28,16 28 55
;
.EQU cR1 = 1000 ; Resistor between ADC input and measured voltage
.EQU cR2 = 1000 ; Resistor between ADC input and ground
.EQU cRin = 8250 ; Input resistance ADC, experimental
;
; Other sSoft switches
;
.EQU cNMode = 3 ; number o0f measurements before mode changes
.EQU cDecSep = ',' ; decimal separator for numbers displayed
.EQU c1kSep = '.' ; thousands separator
.EQU nMeasm = 4 ; number of measurements per second
.IF (nMeasm<4)||(nMeasm>7)
.ERROR "Number of measurements outside acceptable range"
.ENDIF
;
; ================================================
; Hardware connections
; ================================================
; ___ ___
; RESET |1 |_| 28| Prescaler divide by 16 output
; RXD |2 A 27|
; TXD |3 T 26|
; Time inp |4 M 25|
; |5 E 24| Mode select input, 0..2.56 V
; Count in |6 L 23| Voltage input, 0..2.56 V
; VCC |7 22| GND
; GND |8 A 21| AREF (+2.56 V, output)
; XTAL1 |9 T 20| AVCC input
; XTAL2 |10 m 19| SCK/LCD-E
; |11 e 18| MISO/LCD-RS
; |12 g 17| MOSI/LCD-D7
; |13 a 16| LCD-D6
; LCD-D4 |14 8 15| LCD-D5
; |_________|
;
;
; ================================================
; Derived constants
; ================================================
;
.EQU cR2c = (cR2 * cRin) / (cR2+cRin)
.EQU cMultiplier = (641 * (cR1+cR2c))/cR2c ; used for voltage
multiplication
.EQU cMaxVoltage = 1024*cMultiplier/256 ; in mV
.EQU cSafeVoltage = (cMaxVoltage * 5000) / 2560
.EQU cTDiv = 1000/nMeasm ; interval per measurement update
; calculating the CTC and prescaler values for TC1 (frequency
measurement)
.SET cCmp1F = cFreq/32 ; CTC compare value with counter prescaler =
8
.SET cPre1F = (1<<WGM12)|(1<<CS11) ; CTC and counter prescaler = 8
.IF cFreq>2097120
.SET cCmp1F = cFreq/256 ; CTC compare value with counter
prescaler = 64
.SET cPre1F = (1<<WGM12)|(1<<CS11)|(1<<CS10) ; counter
prescaler = 64
.ENDIF
.IF cFreq>16776960
.SET cCmp1F = cFreq/1024 ; CTC compare value with counter
prescaler = 256
.SET cPre1F = (1<<WGM12)|(1<<CS12) ; counter prescaler = 256
.ENDIF
; calculating the CTC and counter prescaler values for TC2 (LCD/
UART update)
.SET cCmp2 = cFreq/8000
.SET cPre2 = (1<<CS21) ; counter prescaler = 8
.IF cFreq>2040000
.SET cCmp2 = cFreq/32000
.SET cPre2 = (1<<CS21)|(1<<CS20) ; counter prescaler = 32
.ENDIF
.IF cFreq>8160000
.SET cCmp2 = cFreq/64000
.SET cPre2 = (1<<CS22) ; counter prescaler = 64
.ENDIF
.IF cFreq>16320000
.SET cCmp2 = cFreq/128000 ; counter prescaler = 128
.SET cPre2 = (1<<CS22)|(1<<CS20)
.ENDIF
;
; Uart constants
;
.IF cUart
.EQU cNul = $00
.EQU cClrScr = $0C
.EQU cCr = $0D
.EQU cLf = $0A
.ENDIF
;
; Debug definitions for testing
;
; (none)
;
; ================================================
; Register definitons
; ================================================
;
; R0 used for LPM and for calculation purposes
.DEF rRes1 = R1 ; Result byte 1
.DEF rRes2 = R2 ; Result byte 2
.DEF rRes3 = R3 ; Result byte 3
.DEF rRes4 = R4 ; Result byte 4
.DEF rDiv1 = R5 ; Divisor byte 1
.DEF rDiv2 = R6 ; Divisor byte 2
.DEF rDiv3 = R7 ; Divisor byte 3
.DEF rDiv4 = R8 ; Divisor byte 4
.DEF rCpy1 = R9 ; Copy byte 1
.DEF rCpy2 = R10 ; Copy byte 2
.DEF rCpy3 = R11 ; Copy byte 3
.DEF rCpy4 = R12 ; Copy byte 4
.DEF rCtr1 = R13 ; Counter/Timer byte 1
.DEF rCtr2 = R14 ; Counter/Timer byte 2
.DEF rCtr3 = R15 ; Counter/Timer byte 3
.DEF rmp = R16 ; Multipurpose register outside interrupts
.DEF rimp = R17 ; Multipurpose register inside interrupts
.DEF rSreg = R18 ; Save status register inside interrupts
.DEF rTDiv = R19 ; Internal divider for TC2 count down
.DEF rMode = R20 ; Current mode of operation
.DEF rNMode = R21 ; Number of inadequate measurements
.DEF rir = R22 ; interrim calculation register
.DEF rFlg = R23 ; Flag register
.EQU bCyc = 2 ; measure cycle ended
.EQU bMode = 3 ; measuring mode, 1 = frequency, 0 = time
.EQU bEdge = 4 ; measured edge, 1 = rising, 0 = falling
.EQU bOvf = 5 ; overflow bit
.EQU bAdc = 6 ; ADC conversion complete flag bit
.EQU bUartRxLine = 7 ; Uart line complete flag bit
.DEF rDelL = R24 ; delay counter for LCD, LSB
.DEF rDelH = R25 ; dto., MSB
; X = R26..R27 used for calculation purposes
; Y = R28..R29: free
; Z = R30..R31 used for LPM and calculation purposes
;
; ================================================
; SRAM definitions
; ================================================
;
.DSEG
.ORG Sram_Start
;
; Result display space in SRAM
;
sResult:
.BYTE 32
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
;
.IF cUart
.EQU UartRxbLen = 38 ; Buffer length in bytes
;
sUartFlag: ; flag register for Uart
.BYTE 1
.EQU bUMonU = 0 ; displays voltage over Uart
.EQU bUMonF = 1 ; displays frequency over Uart
; free: bits 2..7
sUartMonUCnt: ; counter for Monitoring voltage
.BYTE 1
sUartMonURpt: ; counter preset for monitoring voltage
.BYTE 1
sUartMonFCnt: ; counter for Monitoring frequency
.BYTE 1
sUartMonFRpt: ; counter preset for monitoring voltage
.BYTE 1
sUartRxBp: ; buffer pointer
.BYTE 1
sUartRxBs: ; buffer
.BYTE UartRxbLen
sUartRxBe: ; buffer end
.ENDIF
;
; Main interval timer characteristics
;
sTMeas: ; ms per measuring interval (default: 250)
.BYTE 1
;
; ADC result
;
sAdc0L: ; ADC result, channel 0, LSB
.BYTE 1
sAdc0H: ; ADC result, channel 0, MSB
.BYTE 1
sAdc1L: ; ADC result, channel 1, LSB
.BYTE 1
sAdc1H: ; ADC result, channel 1, MSB
.BYTE 1
;
; Interim storage for counter value during time measurement
;
sCtr:
.BYTE 4
;
; ================================================
; Selected mode flags
; ================================================
;
; Mode Measuring Prescale Display
; ---------------------------------------------
; 0 Frequency 16 Frequency
; 1 Frequency 1 Frequency
; 2 Time HL 1 Frequency
; 3 Time HL 1 Rounds per Minute
; 4 Time HL 1 Time
; 5 Time H 1 Time
; 6 Time L 1 Time
; 7 PW ratio H 1 Pulse width ratio H %
; 8 PW ratio L 1 Pulse width ratio L %
; 9 none - Voltage only
; (for a single line LCD)
;
.EQU cModeFrequency16 = 0
.EQU cModeFrequency = 1
.EQU cModeTimeFreq = 2
.EQU cModeTimeRpm = 3
.EQU cModeTimeTimeHL = 4
.EQU cModeTimeTimeH = 5
.EQU cModeTimeTimeL = 6
.EQU cModeTimePwrH = 7
.EQU cModeTimePwrL = 8
.EQU cModeVoltage = 9
;
sModeSlct: ; Selected mode
.BYTE 1
sModeNext: ; next selected mode
.BYTE 1
;
; ==================================================
; Info on timer and counter interrupt operation
; ==================================================
;
; Clock => Presc2 => TC2 => CTC => rTDiv =>
; ADC0 conversion => ADC1 conversion => bAdc-flag
;
; Main interval timer TC2
; - uses TC2 as 8-bit-CTC, with compare interrupt
; - starts a ADC conversion
; - on ADC conversion complete:
; * store ADC result
; * convert ADC result
; * if a new counter result: convert this
; * if Uart connected and monitoring f/U: display on Uart
; * if LCD connected and display mode: display f/U result
;
; Operation at 16 MHz clock:
; cFreq => Prescaler/128 => CTC(125) => rTDiv(250)
; 16MHz => 125 kHz => 1 kHz => 4 Hz
;
; Frequeny counting modes (Mode = 0 and 1)
; - uses TC0 as 8-bit-counter to count positive edges
; - uses TC1 as 16-bit-counter to time-out the counter after 250
ms
;
; Timer modes (Mode = 2 to 8)
; - uses edge detection on external INT0 for timeout
; - uses TC1 as 16-bit-counter to time-out from edge to edge
;
; Voltage only (Mode = 9)
; - Timers TC0 and TC1 off
; - Timer TC2 times interval
;
; ==============================================
; Reset and Interrupt Vectors starting here
; ==============================================
;
.CSEG
.ORG $0000
;
; Reset/Intvectors
;
rjmp Main ; Reset
rjmp Int0Int; Int0
reti ; Int1
rjmp TC2CmpInt ; TC2 Comp
reti ; TC2 Ovf
reti ; TC1 Capt
rjmp Tc1CmpAInt ; TC1 Comp A
reti ; TC1 Comp B
rjmp Tc1OvfInt ; TC1 Ovf
rjmp TC0OvfInt ; TC0 Ovf
reti ; SPI STC
.IF cUart
rjmp SioRxcIsr ; USART RX
.ELSE
reti ; USART RX
.ENDIF
reti ; USART UDRE
reti ; USART TXC
rjmp AdcCcInt ; ADC Conv Compl
reti ; EERDY
reti ; ANA_COMP
reti ; TWI
reti ; SPM_RDY
;
; =============================================
;
; Interrupt Service Routines
;
; =============================================
;
; TC2 Compare Match Interrupt
; counts rTDiv down, if zero: starts an AD conversion
;
TC2CmpInt:
in rSreg,SREG ; save SREG
dec rTDiv ; count down
brne TC2CmpInt1 ; not zero, interval not ended
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start ADC conversion
lds rTDiv,sTMeas ; restart interval timer
TC2CmpInt1:
out SREG,rSreg ; restore SREG
reti
;
; External Interrupt INT0 Service Routine
; active in modes 2 to 6 (measuring the signal duration),
; detects positive going edges of the input
; INT1, TC1 is in free running mode,
; reads the current counter state of TC1,
; copies it to the result registers,
; clears the counter and restarts it
;
Int0Int:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for
copy
rjmp Int0Int1 ; 4, no, last result hasn't been read
in rCpy1,TCNT1L ; 4, read timer 1 LSB
in rCpy2,TCNT1H ; 5, dto., MSB
mov rCpy3,rCtr2 ; 6, copy the counter bytes
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
cbr rFlg,1<<bEdge ; 9, set falling edge
sbic PIND,2 ; 10/11, check if input = 0
sbr rFlg,1<<bEdge ; 11, no, set edge flag to rising
Int0Int1: ; 4/11
ldi rimp,0 ; 5/12, reset the timer
out TCNT1H,rimp ; 6/13, set TC1 zero to restart
out TCNT1L,rimp ; 7/14
mov rCtr1,rimp ; 8/15, clear the upper bytes
mov rCtr2,rimp ; 9/16
mov rCtr3,rimp ; 10/17
out SREG,rSreg ; 11/18, restore SREG
reti ; 15/22
;
; TC1 Compare Match A Interrupt Service Routine
; active in modes 0 and 1 (measuring the number of
; sigals on the T1 input), timeout every 0.25s,
; reads the counter TC0, copies the count to
; the result registers and clears TC0
;
Tc1CmpAInt:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for
copy
rjmp TC1CmpAInt1 ; 4, no, last result hasn't been read
in rCpy1,TCNT0 ; 4, read counter TC0
mov rCpy2,rCtr1 ; 5, copy counter bytes to result
mov rCpy3,rCtr2 ; 6
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
Tc1CmpAInt1: ; 4/8
ldi rimp,0 ; 5/9, clear counter
out TCNT0,rimp ; 6/10
mov rCtr1,rimp ; 7/11, clear counter bytes
mov rCtr2,rimp ; 8/12
mov rCtr3,rimp ; 9/13
out SREG,rSreg ; 10/14, restore SREG
reti ; 14/18
;
; TC1 Overflow Interrupt Service Routine
; active in modes 2 to 6 counting clock cycles to measure time
; increases the upper bytes and detects overflows
;
Tc1OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr2 ; 2, increase byte 3 of the counter
brne Tc1OvfInt1 ; 3/4, no overflow
inc rCtr3 ; 4, increase byte 4 of the counter
brne Tc1OvfInt1 ; 5/6, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 6, set overflow and end of
cycle bit
Tc1OvfInt1: ; 4/6
out SREG,rSreg ; 5/7, restore SREG
reti ; 9/11
;
; TC0 Overflow Interrupt Service Routine
; active in modes 0 and 1 counting positive edges on T1
; increases the upper bytes and detects overflows
;
Tc0OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr1 ; 2, increase byte 2 of the counter
brne Tc0OvfInt1 ; 3/4, no overflow
inc rCtr2 ; 4, increase byte 3 of the counter
brne Tc0OvfInt1 ; 5/6, no overflow
inc rCtr3 ; 6, increase byte 4 of the counter
brne Tc0OvfInt1 ; 7/8, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 8, set overflow bit
Tc0OvfInt1: ; 4/6/8
out SREG,rSreg ; 5/7/9, restore SREG
reti ; 9/11/13
;
; Uart RxC Interrupt Service Routine
; receives a character, signals errors, echoes it back,
; puts it into the SRAM line buffer, checks for carriage
; return characters, if yes echoes additional linefeed
; and sets line-complete flag
;
.IF cUart
SioRxCIsr:
in rSreg,SREG ; 1, Save SReg
in rimp,UCSRA ; 2, Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; 3, isolate error bits
in rimp,UDR ; 4, read character from UART
breq SioRxCIsr1 ; 5/6, no errors
ldi rimp,'*' ; 6, signal an error
out UDR,rimp ; 7
rjmp SioRxCIsr4 ; 9, return from int
SioRxCIsr1: ; 6
out UDR,rimp ; 7, echo the character
push ZH ; 9, Save Z register
push ZL ; 11
ldi ZH,HIGH(sUartRxBs) ; 12, Load Position for next RX char
lds ZL,sUartRxBp ; 14
st Z+,rimp ; 16, save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; 17, End of buffer?
brcc SioRxCIsr2 ; 18/19, Buffer overflow
sts sUartRxBp,ZL ; 20, Save next pointer position
SioRxCIsr2: ; 19/20
cpi rimp,cCr ; 20/21, Carriage Return?
brne SioRxCIsr3 ; 21/22/23, No, go on
ldi rimp,cLf ; 22/23, Echo linefeed
out UDR,rimp ; 23/24
sbr rFlg,(1<<bUartRxLine) ; 24/25, Set line complete flag
rjmp SioRxCIsr3a
SioRxCIsr3: ; 22/23/24/25
cpi rimp,cLf
brne SioRxCIsr3a
sbr rFlg,(1<<bUartRxLine)
SioRxCIsr3a:
pop ZL ; 24/25/26/27, restore Z-register
pop ZH ; 26/27/28/29
SioRxCIsr4: ; 9/26/27/28/29
out SREG,rSreg ; 10/27/28/29/30, restore SREG
reti ; 14/31/32/33/34, return from Int
.ENDIF
;
; ADC has completed a conversion
; used in all modes, ADC has completed a conversion
; if ADMUX channel is 0 then set ADMUX=1 and start
; another coversion
; if ADMUX channel is 1 he set ADMUX=0, disable the ADC
; and set teh ADC cycle end flag
;
.EQU cStopAdc = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
.EQU cStartAdc = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|cStopAdc
AdcCcInt:
in rSreg,SREG ; 1, save SREG
in rimp,ADMUX ; 2, read the current channel info
sbrc rimp,0 ; 3/4, jump if channel = 0
rjmp AdcCcInt1 ; 5
sbr rimp,1 ; 5, set channel MUX to one
out ADMUX,rimp ; 6
in rimp,ADCL ; 7, read result LSB
sts sAdc0L,rimp ; 9, store result LSB
in rimp,ADCH ; 10, read result MSB
sts sAdc0H,rimp ; 12, store result MSB
ldi rimp,cStartAdc
out ADCSRA,rimp ; 14, start next conversion
out SREG,rSreg ; 15, restore SREG
reti ; 19
AdcCcInt1: ; 5
cbr rimp,1 ; 6, set MUX to channel 0
out ADMUX,rimp ; 7
in rimp,ADCL ; 8, read result LSB
sts sAdc1L,rimp ; 10, store result LSB
in rimp,ADCH ; 11, read result MSB
sts sAdc1H,rimp ; 13, store result MSB
sbr rFlg,1<<bAdc ; 14, set flag bit
ldi rimp,cStopAdc ; 15, ADC off
out ADCSRA,rimp ; 16, switch ADC off
out SREG,rSreg ; 17, restore SREG
reti ; 21
;
; ================================================
; Common subroutines
; ================================================
;
; Setting timer/counter modes for measuring
;
SetModeNext:
rcall ClrTc ; clear the timers TC0 and TC1, disable INT0
lds rmp,sModeNext ; read next mode
mov rMode,rmp ; copy to current mode
ldi ZH,HIGH(SetModeTab)
ldi ZL,LOW(SetModeTab)
add ZL,rmp
ldi rmp,0
adc ZH,rmp
ijmp
; Table mode setting
SetModeTab:
rjmp SetMode0 ; f div 16, f
rjmp SetMode1 ; f, f
rjmp SetModeT ; t, f
rjmp SetModeT ; t, u
rjmp SetModeT ; t, t
rjmp SetModeE ; th, t
rjmp SetModeE ; tl, t
rjmp SetModeE ; th, p
rjmp SetModeE ; tl, p
ret ; U, U
;
; Set counters/timers to mode 0
; TC0 counts input signals (positive edges)
; TC1 times the gate at 250 ms
; INT0 disabled
;
SetMode0:
cbi pPresc,bPresc ; enable prescaler
rjmp SetModeF ; frequency measurement
;
; Set counters/timers to mode 1
;
SetMode1:
sbi pPresc,bPresc ; disable prescaler
; Set timer/counter mode to frequency measurement
SetModeF:
ldi rmp,HIGH(cCmp1F) ; set the compare match high value
out OCR1AH,rmp
ldi rmp,LOW(cCmp1F) ; set the compare match low value
out OCR1AL,rmp
ldi rmp,0xFF ; disable the compare match B
out OCR1BH,rmp
out OCR1BL,rmp
ldi rmp,0 ; CTC mode
out TCCR1A,rmp
ldi rmp,cPre1F ; set the prescaler value for TC1
out TCCR1B,rmp
ldi rmp,(1<<CS02)|(1<<CS01)|(1<<CS00) ; count rising edges
on T0
out TCCR0,rmp
ldi rmp,(1<<OCIE2)|(1<<OCIE1A)|(1<<TOIE0) ; enable TC2Cmp,
TC1CmpAInt and TC0OverflowInt
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement
;
SetModeT:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00) ; sleep enable,
positive edges on INT0 interrupt
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement, all edges
;
SetModeE:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC00) ; sleep enable, any logical
change on INT0 interrupts
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
;
; clears the timers and resets the upper bytes
;
ClrTc:
clr rmp ; disable INT0
out GICR,rmp
clr rmp ; stop the counters/timers
out TCCR0,rmp ; stop TC0 counting/timing
out TCCR1B,rmp ; stop TC1 counting/timing
out TCNT0,rmp ; clear TC0
out TCNT1L,rmp ; clear TC1
out TCNT1H,rmp
clr rCtr1 ; clear upper bytes
clr rCtr2
clr rCtr3
ldi rmp,1<<OCIE2 ; enable only output compare of TC2 ints
out TIMSK,rmp ; timer int disable
ret
;
; =======================================================
; Math routines
; =======================================================
;
; Divides cFreq/256 by the timer value in rDiv4:rDiv3:rDiv2:rDiv1
; yields frequency in R4:R3:R2:(Fract):R1
;
Divide:
clr rmp ; rmp:R0:ZH:ZL:XH:XL is divisor
clr R0
clr ZH
ldi ZL,BYTE3(cFreq/256) ; set divisor
ldi XH,BYTE2(cFreq/256)
ldi XL,BYTE1(cFreq/256)
clr rRes1 ; set result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
Divide1:
lsl XL ; multiply divisor by 2
rol XH
rol ZL
rol ZH
rol R0
rol rmp
cp ZL,rDiv1 ; compare with divident
cpc ZH,rDiv2
cpc R0,rDiv3
cpc rmp,rDiv4
brcs Divide2
sub ZL,rDiv1
sbc ZH,rDiv2
sbc R0,rDiv3
sbc rmp,rDiv4
sec
rjmp Divide3
Divide2:
clc
Divide3:
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc Divide1
ret
;
; Multiply measured time in rRes4:rRes3:rRes2:rRes1 by 65536 / fq
(MHz)
; rmp:R0 are the upper bytes of the input
; ZH:ZL:rDiv4:rDiv3:rDiv2:rDiv1 is the interim result
; XH:XL is the multiplicator
; result is in rRes4:rRes3:rRes2:rRes1
;
.EQU cMulti = 65536000 / (cFreq/1000)
;
Multiply:
ldi XH,HIGH(cMulti) ; set multiplicator
ldi XL,LOW(cMulti)
clr ZH
clr ZL
clr rDiv4
clr rDiv3
clr rDiv2
clr rDiv1
clr R0
clr rmp
Multiply1:
cpi XL,0
brne Multiply2
cpi XH,0
breq Multiply4
Multiply2:
lsr XH
ror XL
brcc Multiply3
add rDiv1,rRes1
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
adc ZL,R0
adc ZH,rmp
Multiply3:
lsl rRes1
rol rRes2
rol rRes3
rol rRes4
rol R0
rol rmp
rjmp Multiply1
Multiply4:
ldi rmp,128 ; round result
clr R0
add rDiv2,rmp
adc rDiv3,R0
adc rDiv4,R0
adc ZL,R0
adc ZH,R0
mov rRes1,rDiv3 ; move result
mov rRes2,rDiv4
mov rRes3,ZL
mov rRes4,ZH
ret
;
; Display seconds at buffer end
;
DisplSec:
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'u'
st X+,rmp
ldi rmp,'s'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ret
;
; An overflow has occurred during pulse width calculation
;
PulseOvflw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
st X+,rmp
.IF cDisplay8
ldi ZH,HIGH(2*TxtPOvflw8)
ldi ZL,LOW(2*TxtPOvflw8)
ldi rmp,7
.ELSE
ldi ZH,HIGH(2*TxtPOvflw16)
ldi ZL,LOW(2*TxtPOvflw16)
ldi rmp,15
.ENDIF
PulseOvflw1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne PulseOvflw1
ret
.IF cDisplay8
TxtPOvflw8:
.DB ":error! "
.ELSE
TxtPOvflw16:
.DB ":error calcul.! "
.ENDIF
;
; ======================================================
; Pulse width calculations
; ======================================================
;
; Calculate the pulse width ratio
; active cycle time is in rDelH:rDelL:R0:rmp
; total cycle time is in rDiv
; result will be in rRes
; overflow: carry flag is set
;
CalcPwO: ; overflow
sec
ret
CalcPw:
mov rRes1,rmp ; copy active cycle time to rRes
mov rRes2,R0
mov rRes3,rDelL
mov rRes4,rDelH
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 4
rol rRes2
rol rRes3

http://www.avr-asm-tutorial.net/avr_de/fcount/fcount_m8_v3.html (1 of 4)1/20/2009 7:39:38 PM


40 MHz-Frequenzzähler mit ATmega8, Quellcode

rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
mov XL,rRes1 ; copy to Z:X
mov XH,rRes2
mov ZL,rRes3
mov ZH,rRes4
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO
add rRes1,XL ; * 24
adc rRes2,XH
adc rRes3,ZL
adc rRes4,ZH
clr ZH ; clear the four MSBs of divisor
clr ZL
clr XH
mov XL,rDelH ; * 256
mov rDelH,rDelL
mov rDelL,R0
mov R0,rmp
clr rmp
lsl R0 ; * 512
rol rDelL
rol rDelH
rol XL
rol XH
lsl R0 ; * 1024
rol rDelL
rol rDelH
rol XL
rol XH
sub rmp,rRes1 ; * 1000
sbc R0,rRes2
sbc rDelL,rRes3
sbc rDelH,rRes4
sbc XL,ZH
sbc XH,ZH
cp XL,rDiv1 ; overflow?
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcc CalcPwO
clr rRes1 ; clear result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
CalcPw1: ; dividing loop
lsl rmp ; multiply by 2
rol R0
rol rDelL
rol rDelH
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1 ; compare with divisor
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw2 ; smaller, roll zero in
sub XL,rDiv1 ; subtract divisor
sbc XH,rDiv2
sbc ZL,rDiv3
sbc ZH,rDiv4
sec ; roll one in
rjmp CalcPw3
CalcPw2:
clc
CalcPw3: ; roll result
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc CalcPw1 ; roll on
lsl rDelL ; round result
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw4
ldi rmp,1 ; round up
add rRes1,rmp
ldi rmp,0
adc rRes2,rmp
adc rRes3,rmp
adc rRes4,rmp
CalcPw4:
tst rRes4 ; check > 1000
brne CalcPwE
tst rRes3
brne CalcPwE
ldi rmp,LOW(1001)
cp rRes1,rmp
ldi rmp,HIGH(1001)
cpc rRes2,rmp
brcc CalcPwE
clc ; no error
ret
CalcPwE: ; error
sec
ret
;
; Display the binary in R2:R1 in the form " 100,0%"
;
DisplPw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
ldi rmp,' '
st X+,rmp
st X+,rmp
clr R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecX2
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall DisplDecX2
ldi ZL,10
inc R0
rcall DisplDecX2
ldi rmp,cDecSep
st X+,rmp
ldi rmp,'0'
add rmp,rRes1
st X+,rmp
ldi rmp,'%'
st X+,rmp
.IF ! cDisplay8
ldi rmp,8
ldi ZL,' '
DisplPw1:
st X+,ZL
dec rmp
brne DisplPw1
.ENDIF
ret
;
; If the first characters in the result buffer are empty,
; place the character in ZL here and add equal, if possible
;
DisplMode:
ldi XH,HIGH(sResult+1) ; point to result buffer
ldi XL,LOW(sResult+1)
ld rmp,X ; read second char
cpi rmp,' '
brne DisplMode1
ldi rmp,'='
st X,rmp
DisplMode1:
sbiw XL,1
ld rmp,X ; read first char
cpi rmp,' '
brne DisplMode2
st X,ZL
DisplMode2:
ret
;
;=================================================
; Display binary numbers as decimal
;=================================================
;
; Converts a binary in R2:R1 to a digit in X
; binary in Z
;
DecConv:
clr rmp
DecConv1:
cp R1,ZL ; smaller than binary digit?
cpc R2,ZH
brcs DecConv2 ; ended subtraction
sub R1,ZL
sbc R2,ZH
inc rmp
rjmp DecConv1
DecConv2:
tst rmp
brne DecConv3
tst R0
brne DecConv3
ldi rmp,' ' ; suppress leading zero
rjmp DecConv4
DecConv3:
subi rmp,-'0'
DecConv4:
st X+,rmp
ret
;
; Display fractional number in R3:R2:(Fract)R1
;
DisplFrac:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
.ENDIF
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DisplDecY2
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecY2
.IF ! cDisplay8
ldi rmp,c1kSep
tst R0
brne DisplFrac0
ldi rmp,' '
DisplFrac0:
st X+,rmp
.ENDIF
ldi ZL,100
rcall DisplDecY1
ldi ZL,10
rcall DisplDecY1
ldi rmp,'0'
add rmp,R2
st X+,rmp
tst R1 ; fraction = 0?
brne DisplFrac1
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
st X+,rmp
st X+,rmp
.ENDIF
ret
DisplFrac1:
ldi rmp,cDecSep
st X+,rmp
.IF cDisplay8
ldi ZL,2
.ELSE
ldi ZL,3
.ENDIF
DisplFrac2:
clr rRes3
clr rRes2
mov R0,rRes1 ; * 1
lsl rRes1 ; * 2
adc rRes2,rRes3
lsl rRes1 ; * 4
rol rRes2
add rRes1,R0 ; * 5
adc rRes2,rRes3
lsl rRes1 ; * 10
rol rRes2
ldi rmp,'0'
add rmp,rRes2
st X+,rmp
dec ZL
brne DisplFrac2
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X+,rmp
.ENDIF
ret
;
; Convert a decimal in R4:R3:R2, decimal in ZH:ZL
;
DisplDecY2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY2a:
cp rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecY2b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecY2a
DisplDecY2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY2c
ldi rmp,' '
DisplDecY2c:
st X+,rmp
ret
;
; Convert a decimal decimal in R:R2, decimal in ZL
;
DisplDecY1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY1a:
cp rRes2,ZL
cpc rRes3,rDiv2
brcs DisplDecY1b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecY1a
DisplDecY1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY1c
ldi rmp,' '
DisplDecY1c:
st X+,rmp
ret
;
; Display a 4-byte-binary in decimal format on result line 1
; 8-bit-display: "12345678"
; 16-bit-display: " 12.345.678 Hz "
;
Displ4Dec:
ldi rmp,BYTE1(100000000) ; check overflow
cp rRes1,rmp
ldi rmp,BYTE2(100000000)
cpc rRes2,rmp
ldi rmp,BYTE3(100000000)
cpc rRes3,rmp
ldi rmp,BYTE4(100000000)
cpc rRes4,rmp
brcs Displ4Dec1
rjmp CycleOvf
Displ4Dec1:
clr R0 ; suppress leading zeroes
ldi XH,HIGH(sResult) ; X to result buffer
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' ' ; clear the first two digits
st X+,rmp
st X+,rmp
.ENDIF
ldi ZH,BYTE3(10000000) ; 10 mio
ldi ZL,BYTE2(10000000)
ldi rmp,BYTE1(10000000)
rcall DisplDecX3
ldi ZH,BYTE3(1000000) ; 1 mio
ldi ZL,BYTE2(1000000)
ldi rmp,BYTE1(1000000)
rcall DisplDecX3
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec2
ldi rmp,' '
Displ4Dec2:
st X+,rmp
.ENDIF
ldi ZH,BYTE3(100000) ; 100 k
ldi ZL,BYTE2(100000)
ldi rmp,BYTE1(100000)
rcall DisplDecX3
ldi ZH,HIGH(10000) ; 10 k
ldi ZL,LOW(10000)
rcall DisplDecX2
ldi ZH,HIGH(1000) ; 1 k
ldi ZL,LOW(1000)
rcall DisplDecX2
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec3
ldi rmp,' '
Displ4Dec3:
st X+,rmp
.ENDIF
ldi ZL,100 ; 100
rcall DisplDecX1
ldi ZL,10
rcall DisplDecX1
ldi rmp,'0' ; 1
add rmp,R1
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL:rmp
;
DisplDecX3:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; subtractor for byte 4
DisplDecX3a:
cp rRes1,rmp ; compare
cpc rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecX3b ; ended
sub rRes1,rmp ; subtract
sbc rRes2,ZL
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecX3a
DisplDecX3b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX3c
ldi rmp,' '
DisplDecX3c:
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL
;
DisplDecX2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX2a:
cp rRes1,ZL
cpc rRes2,ZH
cpc rRes3,rDiv2
brcs DisplDecX2b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,ZH
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecX2a
DisplDecX2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX2c
ldi rmp,' '
DisplDecX2c:
st X+,rmp
ret
;
; Convert a decimal in R2:R1, decimal in ZL
;
DisplDecX1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX1a:
cp rRes1,ZL
cpc rRes2,rDiv2
brcs DisplDecX1b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,rDiv2
inc rDiv1
rjmp DisplDecX1a
DisplDecX1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX1c
ldi rmp,' '
DisplDecX1c:
st X+,rmp
ret
;
;=================================================
; Delay routines
;=================================================
;
Delay10ms:
ldi rDelH,HIGH(10000)
ldi rDelL,LOW(10000)
rjmp DelayZ
Delay15ms:
ldi rDelH,HIGH(15000)
ldi rDelL,LOW(15000)
rjmp DelayZ
Delay4_1ms:
ldi rDelH,HIGH(4100)
ldi rDelL,LOW(4100)
rjmp DelayZ
Delay1_64ms:
ldi rDelH,HIGH(1640)
ldi rDelL,LOW(1640)
rjmp DelayZ
Delay100us:
clr rDelH
ldi rDelL,100
rjmp DelayZ
Delay40us:
clr rDelH
ldi rDelL,40
rjmp DelayZ
;
; Delays execution for Z microseconds
;
DelayZ:
.IF cFreq>18000000
nop
nop
.ENDIF
.IF cFreq>16000000
nop
nop
.ENDIF
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
sbiw rDelL,1 ; 2
brne DelayZ ; 2
ret
;
; =========================================
; Main Program Start
; =========================================
;
main:
ldi rmp,HIGH(RAMEND) ; set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
clr rFlg ; set flags to default
;
.IF debug
.EQU number = 100000000
ldi rmp,BYTE4(number)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(number)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(number)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(number)
mov rRes1,rmp
mov rDiv1,rmp
rcall CycleM6
beloop: rjmp beloop
.ENDIF
.IF debugpulse
.EQU nhigh = 100000000
.EQU nlow = 15000
ldi rmp,BYTE4(nhigh)
sts sCtr+3,rmp
ldi rmp,BYTE3(nhigh)
sts sCtr+2,rmp
ldi rmp,BYTE2(nhigh)
sts sCtr+1,rmp
ldi rmp,BYTE1(nhigh)
sts sCtr,rmp
ldi rmp,BYTE4(nlow)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(nlow)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(nlow)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(nlow)
mov rRes1,rmp
mov rDiv1,rmp
sbr rFlg,1<<bEdge
rcall CycleM7
bploop: rjmp bploop
.ENDIF
;
; Clear the output storage
;
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,' '
mov R0,rmp
ldi rmp,32
main1:
st Z+,R0
dec rmp
brne main1
;
; Init the Uart
;
.IF cUart
rcall UartInit
ldi rmp,1<<bUMonU ; monitor U over Uart
sts sUartFlag,rmp
ldi rmp,20 ; 5 seconds
sts sUartMonURpt,rmp ; set repeat default value
ldi rmp,1
sts sUartMonUCnt,rmp
ldi rmp,4 ; 1 seconds
sts sUartMonFCnt,rmp
.ENDIF
;
; Init the LCD
;
.IF cDisplay
rcall LcdInit
.ENDIF
;
; Disable the Analog comparator
;
ldi rmp,1<<ACD
out ACSR,rmp
;
; Disable the external prescaler by 16
;
sbi pPrescD,bPresc ; set prescaler port bit to output
sbi pPresc,bPresc ; disable the prescaler
;
; Init the ADC
;
ldi rmp,(1<<REFS1)|(1<<REFS0) ; int.ref, channel 0
out ADMUX,rmp
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; prescaler = 128
out ADCSRA,rmp
;
; Start main interval timer
;
ldi rmp,cCmp2 ; set Compare Match
out OCR2,rmp
ldi rmp,cPre2|(1<<WGM21) ; CTC mode and prescaler
out TCCR2,rmp
;
; Start timer/counter TC2 interrupts
;
ldi rmp,(1<<OCIE2) ; Interrupt mask
out TIMSK,rmp
;
; Set initial mode to mode 1
;
ldi rmp,1 ; initial mode = 1
sts sModeNext,rmp
rcall SetModeNext
;
sei ; enable interrupts
;
loop:
sleep ; send CPU to sleep
nop
sbrc rFlg,bCyc ; check cycle end
rcall Cycle
sbrc rFlg,bAdc
rcall Interval
.IF cUart
sbrc rFlg,bUartRxLine ; check line complete
rcall UartRxLine ; call line complete
.ENDIF
rjmp loop ; go to sleep
;
; Timer interval for calculation and display
;
Interval:
cbr rFlg,1<<bAdc ; clear flag
lds ZL,sAdc1L ; read ADC channel 1 value
lds ZH,sAdc1H
mov XL,ZL ; copy to X
mov XH,ZH
lsl ZL ; multiply by 2
rol ZH
lsl ZL ; multiply by 4
rol ZH
add ZL,XL ; multiply by 5
adc ZH,XH
lsr ZH ; multiply by 2.5
ror ZL
cpi ZH,10 ; larger than 9?
brcs Interval1
ldi ZH,9 ; set to 9
Interval1:
sts sModeNext,ZH ; store next mode
cp rMode,ZH ; new mode?
breq Interval2 ; continue current mode
rcall SetModeNext ; start new mode
Interval2:
.IF cUart || cDisplay
lds R0,sAdc0L ; read ADC value
lds R1,sAdc0H
rcall cAdc2U ; convert to text
.IF cDisplay
rcall LcdDisplayFT
rcall LcdDisplayU
.ENDIF
.IF cUart
rcall UartMonU
.ENDIF
.ENDIF
ret
;
; Frequency/Time measuring cycle ended, calculate results
;
Cycle:
sbrc rFlg,bOvf ; check overflow
rjmp CycleOvf ; jump to overflow
mov rRes1,rCpy1 ; copy counter
mov rRes2,rCpy2
mov rRes3,rCpy3
mov rRes4,rCpy4
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
mov rDiv1,rRes1 ; copy again
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
.IF cUart
ldi ZH,HIGH(UartMonF) ; put monitoring frequency on stack
ldi ZL,LOW(UartMonF)
push ZL
push ZH
.ENDIF
ldi ZH,HIGH(CycleTab) ; point to mode table
ldi ZL,LOW(CycleTab)
add ZL,rMode ; displace table by mode
brcc Cycle1
inc ZH
Cycle1:
ijmp ; call the calculation routine
; overflow occurred
CycleOvf:
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
ldi XH,HIGH(sResult) ; point to result buffer
ldi XL,LOW(sResult)
.IF cDisplay8
ldi ZH,HIGH(2*TxtOvf8) ; point to short message
ldi ZL,LOW(2*TxtOvf8)
ldi rmp,8
.ELSE
ldi ZH,HIGH(2*TxtOvf16) ; point to long message
ldi ZL,LOW(2*TxtOvf16)
ldi rmp,16
.ENDIF
CycleOvf1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne CycleOvf1
ret
;
.IF cDisplay8
TxtOvf8:
.DB " ovflow"
.ELSE
TxtOvf16:
.DB " overflow "
.ENDIF
; Table with routines for the 8 modes
CycleTab:
rjmp CycleM0
rjmp CycleM1
rjmp CycleM2
rjmp CycleM3
rjmp CycleM4
rjmp CycleM5
rjmp CycleM6
rjmp CycleM7
rjmp CycleM8
ret ; voltage only
;
; Mode 0: Measured prescaled frequency, display frequency
;
CycleM0:
clr R5 ; for detecting an overflow in R5
lsl R1 ; * 2
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 4
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 8
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 16
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 32
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 64
rol R2
rol R3
rol R4
rol R5
tst R5 ; check overflow
breq CycleM0a ; no error
rjmp CycleOvf
CycleM0a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'F'
rjmp DisplMode
;
; Mode 1: Frequency measured, prescale = 1, display frequency
;
CycleM1:
clr rDiv1 ; detect overflow in rDiv1
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4

http://www.avr-asm-tutorial.net/avr_de/fcount/fcount_m8_v3.html (2 of 4)1/20/2009 7:39:38 PM


40 MHz-Frequenzzähler mit ATmega8, Quellcode

rol rDiv1
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
tst rDiv1 ; check overflow
breq CycleM1a ; no error
rjmp CycleOvf
CycleM1a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'f'
rjmp DisplMode
;
; Mode 2: Time measured, prescale = 1, display frequency
;
CycleM2:
rcall Divide
tst rRes4
brne CycleM2a
rcall DisplFrac
ldi ZL,'v'
rcall DisplMode
ret
CycleM2a:
mov rRes1,rRes2 ; number too big, skip fraction
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'v'
rcall DisplMode
ret
;
; Measure time, display rounds per minute
;
CycleM3:
rcall Divide
clr R0 ; overflow detection
clr rmp
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
mov rDiv1,rRes1 ; copy
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 32
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 64
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
tst R0 ; overflow?
breq CycleM3a
rjmp CycleOvf
CycleM3a:
sub rRes1,rDiv1
sbc rRes2,rDiv2
sbc rRes3,rDiv3
sbc rRes4,rDiv4
mov rRes1,rRes2
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'r'
st X+,rmp
ldi rmp,'p'
st X+,rmp
ldi rmp,'m'
st X+,rmp
.ENDIF
ldi ZL,'u'
rcall DisplMode
ret
;
; Measure time high+low, display time
;
CycleM4:
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'t'
rcall DisplMode
ret
;
; Measure time high, display time
;
CycleM5:
sbrs rFlg,bEdge
rjmp CycleM5a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'h'
rcall DisplMode
CycleM5a:
ret
;
; Measure time low, display time
;
CycleM6:
sbrc rFlg,bEdge
rjmp CycleM6a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'l'
rcall DisplMode
CycleM6a:
ret
;
; Measure time high and low, display pulse width ratio high in %
; if the edge was negative, store the measured time, if positive
calculate
; rRes and rDiv hold the active low time, sCtr the last active
high time
; to CalcPw: rDelH:rDelL:R0:rmp = active high time
;
CycleM7:
sbrs rFlg,bEdge
rjmp CycleM7a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rRes1,Z+ ; copy counter value
ld rRes2,Z+
ld rRes3,Z+
ld rRes4,Z+
add rDiv1,rRes1 ; add to total time
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
brcs CycleM7b
mov rmp,rRes1 ; copy high value to divisor
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM7b ; error
rcall DisplPw ; display the ratio
ldi ZL,'P'
rjmp DisplMode
CycleM7a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM7b: ; overflow
ldi rmp,'P'
rjmp PulseOvFlw
;
; Measure time high and low, display pulse width ratio low in %
; if the edge was negative, store the measured time, if positive
calculate
; rRes and rDiv hold the active low time, sCtr the last active
high time
; to CalcPw: rDelH:rDelL:R0:rmp = active low time
;
CycleM8:
sbrs rFlg,bEdge
rjmp CycleM8a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rmp,Z+ ; read high-time
ld R0,Z+
ld rDelL,Z+
ld rDelH,Z
add rDiv1,rmp ; add to total time
adc rDiv2,R0
adc rDiv3,rDelL
adc rDiv4,rDelH
mov rmp,rRes1 ; copy the active low time
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM8b ; error
rcall DisplPw ; display the ratio
ldi ZL,'p'
rjmp DisplMode
CycleM8a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM8b: ; overflow
ldi rmp,'p'
rjmp PulseOvFlw
;
; Converts an ADC value in R1:R0 to a voltage for display
; cAdc2U input: ADC value, output: Voltage in V for display
;
cAdc2U:
clr R2 ; clear the registers for left shift in R3:R2
clr R3
ldi rmp,HIGH(cMultiplier) ; Multiplier to R5:R4
mov R5,rmp
ldi rmp,LOW(cMultiplier)
mov R4,rmp
clr XL ; clear result in ZH:ZL:XH:XL
clr XH
clr ZL
clr ZH
cAdc2U1:
lsr R5 ; shift Multiplier right
ror R4
brcc cAdc2U2 ; bit is zero, don't add
add XL,R0 ; add to result
adc XH,R1
adc ZL,R2
adc ZH,R3
cAdc2U2:
mov rmp,R4 ; check zero
or rmp,R5
breq cAdc2U3 ; end of multiplication
lsl R0 ; multiply by 2
rol R1
rol R2
rol R3
rjmp cAdc2U1 ; go on multipying
cAdc2U3:
ldi rmp,$80 ; round up
add XL,rmp
ldi rmp,$00
adc XH,rmp
adc ZL,rmp
adc ZH,rmp
tst ZH ; check overflow
mov R1,XH ; copy result to R2:R1
mov R2,ZL
ldi XH,HIGH(sResult+16) ; point to result
ldi XL,LOW(sResult+16)
ldi rmp,'U'
st X+,rmp
breq cAdc2U5
ldi ZH,HIGH(2*AdcErrTxt)
ldi ZL,LOW(2*AdcErrTxt)
cAdc2U4:
lpm
tst R0
breq cAdc2U6
sbiw ZL,1
st X+,R0
rjmp cAdc2U4
cAdc2U5:
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DecConv
inc R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DecConv
ldi rmp,cDecSep
st X+,rmp
clr ZH
ldi ZL,100
rcall DecConv
ldi ZL,10
rcall DecConv
ldi rmp,'0'
add rmp,R1
st X+,rmp
ldi rmp,'V'
st X,rmp
lds rmp,sResult+17
cpi rmp,' '
brne cAdc2U6
ldi rmp,'='
sts sResult+17,rmp
cAdc2U6:
ret
;
AdcErrTxt:
.DB "overflw",$00
;
; ===========================================
; Lcd display routines
; ===========================================
;
.IF cDisplay ; if display connected
;
; LcdE pulses the E output for at least 1 us
;
LcdE:
sbi PORTB,bLcdE
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
.IF cFreq>2000000
nop
nop
.ENDIF
nop
nop
cbi PORTB,bLcdE
ret
;
; outputs the content of rmp (temporary
; 8-Bit-Interface during startup)
;
LcdRs8:
out PORTB,rmp
rcall LcdE
ret
;
; write rmp as 4-bit-command to the LCD
;
LcdRs4:
mov R0,rmp ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original back
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE
mov rmp,R0 ; restore rmp
ret
;
; write rmp as data over 4-bit-interface to the LCD
;
LcdData4:
push rmp ; save rmp
mov rmp,R0 ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original again
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE
rcall Delay40us
pop rmp ; restore rmp
ret
;
; writes the text in flash to the LCD, number of
; characters in rmp
;
LcdText:
lpm ; read character from flash
adiw ZL,1
rcall LcdData4 ; write to
rcall delay40us
dec rmp
brne LcdText
ret
;
; Inits the LCD with a 4-bit-interface
;
LcdInit:
ldi rmp,0x0F | (1<<bLcdE) | (1<<bLcdRs)
out DDRB,rmp
clr rmp
out PORTB,rmp
rcall delay15ms ; wait for complete self-init
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay4_1ms ; wait for 4.1 ms
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay100us ; wait for 100 us
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay40us ; delay 40 us
ldi rmp,0x02 ; Function set 4-bit-interface
rcall LcdRs8
rcall delay40us
.IF cDisplay2
ldi rmp,0x28 ; 4-bit-interface, two line display
.ELSE
ldi rmp,0x20 ; 4-bit-interface, single line display
.ENDIF
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x08 ; display off
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x01 ; display clear
rcall LcdRs4
rcall delay1_64ms ; delay 1.64 ms
ldi rmp,0x06 ; increment, don't shift
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x0C ; display on
rcall LcdRs4
rcall delay40us
ldi rmp,0x80 ; position on line 1
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
ldi ZH,HIGH(2*LcdInitTxt8)
ldi ZL,LOW(2*LcdInitTxt8)
.ELSE
ldi rmp,16
ldi ZH,HIGH(2*LcdInitTxt16)
ldi ZL,LOW(2*LcdInitTxt16)
.ENDIF
rcall LcdText
.IF cDisplay2
ldi rmp,0xC0 ; line 2
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
.ELSE
ldi XH,HIGH(sResult+25)
ldi XL,LOW(sResult+25)
ldi ZH,HIGH(2*LcdInitTxtMode)
ldi ZL,LOW(2*LcdInitTxtMode)
ldi rmp,6
LcdInitMode:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne LcdInitMode
ldi rmp,16
.ENDIF
rcall LcdText
.ENDIF
ret
.IF cDisplay8
LcdInitTxt8:
.DB "F-CNT V1"
.IF cDisplay2
.DB "-DG4FAC-"
.ENDIF
.ELSE
LcdInitTxt16:
.DB "Freq-counter V01"
.IF cDisplay2
.DB " (C)2005 DG4FAC "
LcdInitTxtMode:
.DB " Mode="
.ENDIF
.ENDIF
;
; Display frequency/time on Lcd
;
LcdDisplayFT:
.IF ! cDisplay2 ; single line display
cpi rMode,cModeVoltage ; voltage display selected?
breq LcdDisplayFT2
.ENDIF
ldi rmp,$80 ; set display position to line 1
rcall LcdRs4
rcall Delay40us
ldi ZH,HIGH(sResult) ; point Z to line buffer
ldi ZL,LOW(sResult)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayFT1:
ld R0,Z+ ; read a char
rcall LcdData4 ; display on LCD
dec rmp
brne LcdDisplayFT1
LcdDisplayFT2:
ret
;
; Display voltage on the display
;
LcdDisplayU:
.IF cDisplay2 ; two-line LCD connected
.IF !cDisplay8
lds rmp,sModeNext
subi rmp,-'0'
sts sResult+31,rmp
.ENDIF
ldi rmp,$C0 ; output to line 2
.ELSE
cpi rMode,cModeVoltage ; check switch
brne LcdDisplayU2
ldi rmp,$80 ; output to line 1
.ENDIF
rcall LcdRs4 ; set output position
rcall Delay40us
ldi ZH,HIGH(sResult+16) ; point to result
ldi ZL,LOW(sResult+16)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayU1:
ld R0,Z+ ; read character
rcall LcdData4
dec rmp ; next char
brne LcdDisplayU1 ; continue with chars
LcdDisplayU2:
ret
;
.ENDIF ; end LCD routines to be included
;
; ===========================================
; Uart routines
; ===========================================
;
.IF cUart
UartInit: ; Init the Uart on startup
.EQU cUbrr = (cFreq/cBaud/16)-1 ; calculating UBRR single speed
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi rmp,HIGH(cUbrr) ; set URSEL to zero, set baudrate msb
out UBRRH,rmp
ldi rmp,LOW(cUbrr) ; set baudrate lsb
out UBRRL,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; set 8 bit
characters
out UCSRC,rmp
ldi rmp,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable RX/TX and
RX-Ints
out UCSRB,rmp
rcall delay10ms ; delay for 10 ms duration
ldi ZH,HIGH(2*txtUartInit)
ldi ZL,LOW(2*txtUartInit)
rjmp UartSendTxt
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
; .EQU UartRxbLen = 38 ; Buffer length in bytes
; sUartFlag: ; flag register for Uart
; .BYTE 1
; .EQU bUMonU = 0 ; displays voltage over Uart
; .EQU bUMonF = 1 ; displays frequency over Uart
; ; free: bits 2..7
; sUartMonUCnt: ; counter for Monitoring voltage
; .BYTE 1
; sUartMonURpt: ; counter preset for monitoring voltage
; .BYTE 1
; sUartRxBp: ; buffer pointer
; .BYTE 1
; sUartRxBs: ; buffer
; .BYTE UartRxbLen
; sUartRxBe: ; buffer end
; .EQU cNul = $00
; .EQU cClrScr = $0C
; .EQU cCr = $0D
; .EQU cLf = $0A
;
UartRxLine:
cbr rFlg,1<<bUartRxLine ; clear line complete flag
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi ZH,HIGH(UartReturn) ; push return adress to stack
ldi ZL,LOW(UartReturn)
push ZL
push ZH
ldi ZH,HIGH(sUartRxBs) ; set Z to Buffer-Start
ldi ZL,LOW(sUartRxBs)
ld rmp,Z+ ; read first character
cpi rmp,'h' ; help?
brne UartRxLine1
rjmp UartHelp
UartRxLine1:
cpi rmp,'?' ; help?
brne UartRxLine2
rjmp UartHelp
UartRxLine2:
cpi rmp,'U' ; monitor U on
brne UartRxLine3
rcall UartGetPar
sec
rjmp UartMonUSetC
UartRxLine3:
cpi rmp,'u' ; monitor U off
brne UartRxLine4
clc
rjmp UartMonUSetC
UartRxLine4:
cpi rmp,'F' ; monitor F on
brne UartRxLine5
rcall UartGetPar
sec
rjmp UartMonFSetC
UartRxLine5:
cpi rmp,'f' ; monitor f off
brne UartRxLine6
clc
rjmp UartMonFSetC
UartRxLine6:
cpi rmp,'p' ; parameter?
brne UartRxLine7
rjmp UartMonPar
UartRxLine7:
ldi ZH,HIGH(2*txtUartUnknown) ; send unknown command
ldi ZL,LOW(2*txtUartUnknown)
ret
UartHelp:
ldi ZH,HIGH(2*txtUartHelp) ; send help text
ldi ZL,LOW(2*txtUartHelp)
ret
UartMonUSetC:
lds rmp,sUartFlag
brcs UartMonUSetC1
cbr rmp,1<<bUMonU ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOff)
ldi ZL,LOW(2*txtUartUOff)
ret
UartMonUSetC1:
brne UartMonUSetC2
sts sUartMonURpt,R0
sts sUartMonUCnt,R0
UartMonUSetC2:
sbr rmp,1<<bUMonU ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOn)
ldi ZL,LOW(2*txtUartUOn)
ret
UartMonFSetC:
lds rmp,sUartFlag
brcs UartMonFSetC1
cbr rmp,1<<bUMonF ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOff)
ldi ZL,LOW(2*txtUartFOff)
ret
UartMonFSetC1:
brne UartMonFSetC2
sts sUartMonFRpt,R0
sts sUartMonFCnt,R0
UartMonFSetC2:
sbr rmp,1<<bUMonF ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOn)
ldi ZL,LOW(2*txtUartFOn)
ret
UartMonPar:
ldi ZH,HIGH(2*txtUartNul)
ldi ZL,LOW(2*txtUartNul);
ldi rmp,'U'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonURpt
rcall UartHexR
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'F'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonFRpt
rjmp UartHexR
;
; Get Parameter from line
;
UartGetPar:
clr R0 ; result register
ld rmp,Z+ ; read char
cpi rmp,cCr ; carriage return
breq UartGetParNoPar
cpi rmp,cLf ; line feed
breq UartGetParNoPar
cpi rmp,'=' ;
brne UartGetParErr
UartGetPar1:
ld rmp,Z+ ; read next char
cpi rmp,cCr ; carriage return?
breq UartGetPar2
cpi rmp,cLf ; line feed?
breq UartGetPar2
subi rmp,'0' ; subtract 0
brcs UartGetParErr
cpi rmp,10 ; larger than 9?
brcc UartGetParErr
mov rir,R0 ; copy to rir
lsl R0 ; * 2
brcs UartGetParErr
lsl R0 ; * 4
brcs UartGetParErr
add R0,rir ; * 5
brcs UartGetParErr
lsl R0 ; * 10
brcs UartGetParErr
add R0,rmp ; add new decimal
brcs UartGetParErr
rjmp UartGetPar1
UartGetPar2:
sez
ret
UartGetParErr:
ldi ZH,HIGH(2*txtUartErr)
ldi ZL,LOW(2*txtUartErr)
rcall UartSendTxt
UartGetParNoPar:
clz ; No parameter set
ret
;
; Hex output over Uart, for debugging
;
UartHexR:
push rmp
swap rmp
rcall UartHexN
pop rmp
UartHexN:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs UartHexN1
subi rmp,-7
UartHexN1:
rjmp UartSendChar
ret
;
; Return from Uart-Routines, displays text in Z
;
UartReturn:
rcall UartSendTxt ; send text in Z
ldi ZH,HIGH(2*txtUartCursor)
ldi ZL,LOW(2*txtUartCursor)
rjmp UartSendTxt
;
; Send character in rmp over Uart
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartSendChar
out UDR,rmp
ret
;
; Monitoring the voltage over the Uart
;
UartMonU:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonU ; displays voltage over Uart
ret
lds rmp,sUartMonUCnt ; read counter
dec rmp
sts sUartMonUCnt,rmp
brne UartMonU2
lds rmp,sUartMonURpt
sts sUartMonUCnt,rmp
ldi ZH,HIGH(sResult+16)
ldi ZL,LOW(sResult+16)
ldi rmp,8
UartMonU1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonU1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonU1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonU2:
ret
;
; Monitor frequency over UART
;
UartMonF:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonF ; displays frequency over Uart
ret
lds rmp,sUartMonFCnt ; read counter
dec rmp
sts sUartMonFCnt,rmp
brne UartMonF2
lds rmp,sUartMonFRpt
sts sUartMonFCnt,rmp
ldi ZH,HIGH(sResult)

http://www.avr-asm-tutorial.net/avr_de/fcount/fcount_m8_v3.html (3 of 4)1/20/2009 7:39:38 PM


40 MHz-Frequenzzähler mit ATmega8, Quellcode

ldi ZL,LOW(sResult)
ldi rmp,16
UartMonF1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonF1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonF1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonF2:
ret
;
; Send text from flash to UART, null byte ends transmit
;
UartSendTxt:
lpm ; read character from flash
adiw ZL,1
tst R0 ; check end of text
breq UartSendTxtRet
UartSendTxtWait:
sbis UCSRA,UDRE ; wait for empty char
rjmp UartSendTxtWait
out UDR,R0 ; send char
rjmp UartSendTxt
UartSendTxtRet:
ret
;
; Uart text constants
;
txtUartInit:
.DB " ",cClrScr
.DB "************************************************* ",cCr,cLf
.DB "* Frequency- and voltmeter (C)2005 by g.schmidt * ",cCr,cLf
.DB "************************************************* ",cCr,cLf
txtUartMenue:
.DB cCr,cLf,"Commands: <h>elp",cCr,cLf
txtUartCursor:
.DB cCr,cLf,"i> ",cNul
txtUartUnknown:
.DB cCr,cLf,"Unknown command!",cNul,cNul
txtUartUOff:
.DB "Voltage monitoring is off.",cNul,cNul
txtUartUOn:
.DB "Voltage monitoring is on. ",cNul,cNul
txtUartFOff:
.DB "Frequency monitoring is off.",cNul,cNul
txtUartFOn:
.DB "Frequency monitoring is on. ",cNul,cNul
txtUartErr:
.DB "Error in parameter! ",cNul,cNul
txtUartHelp:
.DB cCr,cLf,"Help: ",cCr,cLf
.DB "U[=N](on) or u(Off): monitor voltage output, N=1..255,",cCr,cLf
.DB "F[=N](On) or f(Off): monitor frequency output N=1..255, ",cCr,
cLf
.DB "p: display monitoring parameters, ",cCr,cLf
.DB "h or ?: this text."
txtUartNul:
.DB cNul,cNul
.ENDIF
;
; End of source code
;

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/fcount/fcount_m8_v3.html (4 of 4)1/20/2009 7:39:38 PM


40MHz-Frequenzzähler mit ATmega8

Pfad: Home => AVR-Übersicht => Anwendungen => Frequenzzähler

40MHz-Frequenzzähler mit ATmega8


Diese Anwendung eines AVR beschreibt einen Frequenzzähler mit dem ATMEL ATmega8 mit folgenden Eigenschaften:

● Digital- und Analogeingang, Spannungsmess-Eingang


● Eingangsstufe mit Vorverstärker und Vorteiler durch 16
● Anzeige mit ein- oder zweizeiliger LCD-Anzeige
● Neun Mess- und Anzeigemodi, mit Potentiometer wählbar:
❍ 0: Frequenzmessung mit Vorteiler, Gatezeit 0,25 s, Ergebnis in Hz

❍ 1: Frequenzmessung ohne Vorteiler, Gatezeit 0,25 s, Ergebnis in Hz

❍ 2: Frequenzmessung als Periodenmessung mit Frequenz- umrechnung, Ergebnis in 0,01 Hz bzw. 0,001 Hz

❍ 3: Umdrehungsmessung, ohne Vorteiler, ueber Periodenmessung mit Umrechnung, Ergebnis in Upm

❍ 4: Periodendauer gesamte Schwingung, Ergebnis in Mikrosekunden

❍ 5: Periodendauer High-Periode, Ergebnis in Mikrosekunden

❍ 6: Periodendauer Low-Periode, Ergebnis in Mikrosekunden

❍ 7: Periodenanteil High-Periode, Ergebnis in 0,1%

❍ 8: Periodenanteil Low-Periode, Ergebnis in 0,1%

❍ 9: Spannungsmessung, Ergebnis in 0,001 Volt

● Die Auswahl von Modus 9 (rechter Poti-Anschlag) schaltet die Frequenz-/Zeit-/Periodenmessungen aus.
● SIO-Interface zum Anschluss an PC
● Quarzoszillator 16 MHz

Änderungen gegenüber älteren Versionen


● Autorange wurde entfernt, da die Bedienung sich als holprig erwies.
● Der Vorteiler im Analogteil wurde auf 16 umgestellt (Ausgang von QC auf QD umlöten), damit bis 40 MHz gemessen werden kann. Der Zähler zählt ohne Vorteiler nur Frequenzen bis zu ca. 5 MHz.
● Das serielle Interface wurde um viele Funktionen erweitert (Spannungs- und Frequenzausgabe, Intervall parametergesteuert, Ausgabe der Parameter).

0. Inhalt
● 1. Hardware
❍ 1.1 Eingangsteil

❍ 1.2 Prozessor

❍ 1.3 LCD-Anzeige

❍ 1.4 SIO-Anschluss

❍ 1.5 Aufbauhinweise

● 2. Bedienung
❍ 2.1 Potentiometer für Mode-Auswahl

❍ 2.2 Spannungsmessung

● 3. Software
❍ 3.1 Einstellungen vor dem Assemblieren

❍ 3.2 Fuses

❍ 3.3 Kommentierter Quellcode

1 Hardware
Der Frequenzzähler besteht aus einem Eingangsteil (Vorverstärker und Vorteiler) und dem Prozessor- und Anzeigeteil.

1.1 Eingangsteil

Das Eingangsteil hat einen Analog- und einen Digitaleingang.


Das Signal am Analogeingang wird mit dem schnellen Operationsverstärker NE592 verstärkt. Das Ausgangssignal wird dem Pegel angepasst und dem Schmitt-Trigger-NAND 74HCT132 zugeführt.
Der Digitaleingang wird direkt dem Schmitt-Trigger-NAND zugeführt.
Das Ausgangssignal des Schmitt-Triggers wird, abhängig vom Steuerungssignal des Prozessors, entweder direkt dem Prozessor zum Zählen zugeführt oder vorher im Binärzähler 74HCT93 durch 16 geteilt.

1.2 Prozessorteil

Der Prozessorteil ist um den ATmega8 herum aufgebaut. Der Prozessor wird mit einem Quarz von 16 MHz an den Anschlüssen XTAL1 und XTAL2 getaktet. Die beiden Keramikkondensatoren von 22 pF dienen dem besseren
Anschwingen des Quarzoszillators.
Die Versorgung erfolgt über den GND-Anschluss an Pin 8 und VCC an Pin 7, die mit einem Keramikkondensator von 100 nF abgeblockt sind. Die Versorgung für den AD-Wandler wird über den GND-Anschluss Pin 22 und
über eine Drossel von 22 µH am AVCC-Pin 20 zugeführt, der ebenfalls mit 100 nF geblockt ist. Die interne Referenzspannung wird am AREF-Pin 21 mit einem Folienkondensator von 100 nF geglättet.
Der AD-Wandler-Eingang PC1 ist mit dem Schleifer des Potentiometers verbunden, an dem der Mess- und Anzeigemodus eingestellt wird. Der Widerstand von 100 k begrenzt dessen Ausgangsspannung auf 2,5 V. Wird nur
ein bestimmter Messmode benötigt, kann das Potentiometer auch gegen einen Trimmer oder einen festen Spannungsteiler aus Widerstäden ersetzt werden.
Am AD-Wandler-Kanal ADC0 (PC0) wird über einen Spannungsteiler das Analogsignal für die Spannungsmessung zugeführt. Im dargestellten Fall ist die Messung auf einen Vollausschlag von 5,12 V eingestellt. Durch
Ändern der beiden Teiler-Widerstände kann die Auflösung der Spannungsmessung in weiten Bereichen verändert werden. Der AD-Wandler-Eingang ist wegen des hochohmigen Eingangs gegen Einstreuungen abgeblockt.
Die Signale TXD und RXD stellen das serielle Interface dar und sind mit dem Treiber-IC MAX232 verbunden. Die am MAX232 angeschlossenen Elkos dienen der Spannungserzeugung für die RS232-Signale. Diese liegen
über einen 10-poligen Pfostenstecker an der neunpoligen Buchse an. Die RS232-Signale CTS, DSR und CD sind über die Widerstände 2k2 dauernd aktiviert.
Der I/O-Pin PC5 steuert den Vorteiler. Bei High erfolgt keine Vorteilung, bei Low eine Vorteilung durch 16.
Der Signaleingang aus dem Vorverstärker/Vorteiler wird sowohl dem Eingang INT0, für die Flankenmessung, als auch dem Eingang T0, für die Zählmessung, zugeführt.
Die Portbits PB0 bis PB3 dienen der vierbittigen Ansteuerung des Datenports der LCD-Anzeige. Der E(nable)-Eingang der LCD wird über PB5, der RS-Eingang über PB4 an gesteuert. Der E-Eingang ist bei inaktivem Portbit
über 100 k auf Masse gelegt, um unbeabsichtigte Signale an der LCD zu vermeiden. Am VO-Eingang der LCD ist der Kontrast der Anzeige mit einem Trimmer von 10 k einstellbar.
Die Portbits MOSI, SCK und MISO sowie das RESET-Signal liegen am 10-poligen ISP-Port an, über den der Prozessor in der Schaltung programmiert werden kann. Die rote LED dient der Anzeige, dass der
Programmiervorgang aktiv ist. Über die anliegende Betriebsspannung wird das Programmierinterface mit Strom versorgt.
Der RESET-Eingang ist über ein Widerstand von 10 k mit der Betriebsspannung verbunden.

1.3 LCD-Anzeige

Die LCD-Anzeige ist über den 14-poligen Standardstecker an die Prozessorplatine angeschlossen.
Verwendet werden können ein- und zweizeilige LCD-Anzeigen mit 16 bis 40 Zeichen pro Zeile (einstellbar
per Software).

1.4 SIO-Anschluss

Der Zähler verfügt über einen SIO-Anschluss. Über dieses Interface kann das Messergebnis verfolgt werden. Darüber können auch Ausgabeparameter eingestellt werden.

1.5 Aufbauhinweise

Die gesamte Schaltung wurde auf einer Lochrasterplatine von 10 * 5 cm aufgebaut und mit Kupferlackdraht verdrahtet.

Zwei der Befestigungsschrauben der LCD-Anzeige dienen auch der Befestigung der Lochrasterplatine.

Alle Komponenten, einschließlich einer kleinen Netzteilversorgung und einer 9 V-Batterie für netzunabhängigen Betrieb passen in ein kleines Gehäuse.

2. Bedienung
Die Bedienung ist sehr einfach. Die Auswahl zwischen dem Digital- und dem Analog-Eingang ist nicht erforderlich: angezeigt werden stets beide zusammen. Dazu wird bei offenem Eingang der Trimmer am Analogverstärker
gerade so weit heruntergedreht, dass keine Fehlsignale resultieren.

2.1 Potentiometer für Mode-Auswahl

Am Mode-Potentiometer wird der Anzeige-Modus eingestellt. Bei der Frequenzmessung erfolgt die Auswahl, ob Impulse gezählt werden oder ob die Dauer der Flanken gemessen wird, durch die Modus-Auswahl.

Die Darstellung der Ergebnisse erfolgt bei zweizeiligen LCD-Anzeigen mit 16 Zeichen und mehr folgendermaßen:

Mode Messgröße Messmethode Anzeigenformat


0 Frequenz Zählung, Vorteiler=16 F=99.999.999 Hz
1 Frequenz Zählung, Vorteiler=1 f= 9.999.999 Hz
2 Frequenz Periodenmessung v= 9.999,999 Hz
3 Umdrehungszahl Periodenmessung u= 9.999.999 rpm
4 Periode Periodenmessung t=99.999.999 us
5 High-Periode Periodenmessung h=99.999.999 us
6 Low-Periode Periodenmessung l=99.999.999.us
7 High-Periodenanteil Periodenmessung P=100,0%
8 Low-Periodenanteil Periodenmessung p=100,0%
9 Spannung AD-Wandlung U=9,999V

Bei einzeiligen LCD-Anzeigen wird die Spannung nur angezeigt, wenn Mode 9 eingestellt ist. Bei weniger als 16 Zeichen pro Zeile werden die Tausender-Trennzeichen und die Dimensionen nicht angezeigt. Die Messgrößen
werden nur angezeigt, wenn der Messwert die entsprechenden Positionen nicht benötigt.

2.2 Spannungsmessung

Die am Spannungs-Messeingang anliegende Spannung wird vier Mal pro Sekunde gemessen und angezeigt.

3. Software
Die Software ist vollständig in Assembler geschrieben. Vor dem Assemblieren des Quellcodes sind unbedingt wichtige Einstellungen (siehe 3.1) vorzunehmen. Beim Programmieren in den ATmega8 sind unbedingt noch
dessen Fuses zu verändern (siehe 3.2).

3.1 Einstellungen vor dem Assemblieren

Die folgenden Einstellungen sind vor dem Assemblieren in der Datei fcountV03.asm zu kontrollieren und ggfs. zu ändern:

● Die Schalter debug und debugpulse muessen auf 0 stehen.


● Wenn ein LCD-Display angeschlossen ist, muss cDisplay auf 1 stehen, sonst auf 0.
● Wenn das angeschlossene LCD-Display 8 Zeichen pro Zeile darstellen kann, muss cDisplay8 auf 1 stehen. Wenn es 16 oder 20 Zeichen pro Zeile darstellen kann, muss cDisplay8 auf 0 stehen.
● Wenn das angeschlossene LCD-Display eine einzige Zeile darstellen kann, muss cDisplay2 auf 0 stehen. Wenn es zwei oder mehr Zeilen darstellen kann, muss cDisplay2 auf 1 stehen.
● Wenn die serielle Schnittstelle angeschlossen ist und bedient werden soll, muss cUart auf 1 stehen. Ist keine serielle Schnittstelle angeschlossen oder soll sie nicht verwendet werden, wird cUart auf 0 gesetzt.
● Ist der Vorteiler durch 16 an einem anderen Portbit als PC5 angeschlossen, sind die Ports pPresc und pPrescD sowie das Portbit bPresc entsprechend zu aendern.
● Wird der Prozessortakt mit einer anderen Frequenz als 16 MHz betrieben, ist diese in cFreq anzugeben.
● Soll die serielle Schnittstelle mit einer anderen Baudrate als 9600 arbeiten, ist cBaud entsprechend zu ändern.
● Ist der Vorteiler fuer die Spannungsmessung mit zwei anderen Widerstaenden bestueckt als mit 1M, sind die beiden Werte cR1 und cR2 entsprechend zu aendern. Wenn die angezeigte Spannung wesentlich von der
Eingangsspannung abweicht, ist cRin zu aendern: kleinere Werte fuer cRin ergeben eine hoehere angezeigte Spannung, groeszere eine niedrigere angezeigte Spannung.

3.2 Fuses

Im gelieferten Zustand sind ATmega8-Prozessoren auf den internen RC-Oszillator eingestellt. Damit der ATmega8 mit dem externen Quarz als Oszillator arbeitet, müssen die Fuses umgestellt werden.

Die Einstellungen sind mit dem ATMEL Studio folgendermaßen zu ändern:

Die Einstellungen sind mit PonyProg 2000 sind folgendermaßen zu ändern:

Bitte beachten: Nach dem Ändern der Fuses ist der ATmega8 nur noch ansprechbar, wenn ein Quarz angeschlossen ist oder der Takt extern zugeführt wird! Beim Studio ist daher der XTAL Jumper zu stecken.

3.3 Kommentierter Quellcode

Der Quellcode liegt in HTML-Form (hier) und als Assembler-Quelltext (hier) vor. In der Textdatei LiesMich3.txt sind weitere Hinweise zur Programmierung und Bedienung zusammengestellt.

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/fcount/fcount_m8.html1/20/2009 7:40:23 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm

; ****************************************************
; * Frequenzzaehler, Drehzahlmesser und Voltmeter *
; * fuer ATmega8 bei 16 MHz Taktfrequenz (Quarzosz.) *
; * ohne Autorange, mit Vorteiler /1 oder /16 *
; * Version 0.3 (C)2009 by info@avr-asm-tutorial.net *
; ****************************************************
;
.INCLUDE "m8def.inc"
;
.EQU debug = 0
.EQU debugpulse = 0
;
; Switches for connected hardware
;
.EQU cDisplay = 1 ; LCD display connected
.EQU cDisplay8 = 0 ; displays 8 characters per line instead of 16
.EQU cDisplay2 = 1 ; two line LCD display connected
.EQU cUart = 1 ; Uart active
; attached prescaler on port C
.EQU pPresc = PORTC ; prescaler by 16 output attached to port C
.EQU pPrescD = DDRC ; data direction of prescaler
.EQU bPresc = 5 ; bit 5 enables prescaler by 16
;
; ================================================
; Other hardware depending stuff
; ================================================
;
.EQU cFreq = 16000000 ; Clock frequency processor in cycles/s
.IF cUart
.EQU cBaud = 9600 ; If Uart active, define Baudrate
.ENDIF
.EQU bLcdE = 5 ; LCD E port bit on Port B
.EQU bLcdRs = 4 ; Lcd RS port bit on Port B
;
; ================================================
; Constants for voltage measurement
; ================================================
;
; Resistor network as pre-divider for the ADC
; --------------------------------------
; R1 R2(k) Meas Accur. MaxVoltage
; kOhm kOhm Volt mV/dig Volt
; --------------------------------------
; 1000 1000 5,12 5 10
; 1000 820 5,68 6 11
; 1000 680 6,32 6 12
; 1000 560 7,13 7 14
; 1000 470 8,01 8 15
; 1000 330 10,32 10 20
; 1000 270 12,04 12 23
; 1000 220 14,20 14 27
; 1000 180 16,78 16 32
; 1000 150 19,63 19 38
; 1000 120 23,98 23 46
; 1000 100 28,16 28 55
;
.EQU cR1 = 1000 ; Resistor between ADC input and measured voltage
.EQU cR2 = 1000 ; Resistor between ADC input and ground
.EQU cRin = 8250 ; Input resistance ADC, experimental
;
; Other sSoft switches
;
.EQU cNMode = 3 ; number o0f measurements before mode changes
.EQU cDecSep = ',' ; decimal separator for numbers displayed
.EQU c1kSep = '.' ; thousands separator
.EQU nMeasm = 4 ; number of measurements per second
.IF (nMeasm<4)||(nMeasm>7)
.ERROR "Number of measurements outside acceptable range"
.ENDIF
;
; ================================================
; Hardware connections
; ================================================
; ___ ___
; RESET |1 |_| 28| Prescaler divide by 16 output
; RXD |2 A 27|
; TXD |3 T 26|
; Time inp |4 M 25|
; |5 E 24| Mode select input, 0..2.56 V
; Count in |6 L 23| Voltage input, 0..2.56 V
; VCC |7 22| GND
; GND |8 A 21| AREF (+2.56 V, output)
; XTAL1 |9 T 20| AVCC input
; XTAL2 |10 m 19| SCK/LCD-E
; |11 e 18| MISO/LCD-RS
; |12 g 17| MOSI/LCD-D7
; |13 a 16| LCD-D6
; LCD-D4 |14 8 15| LCD-D5
; |_________|
;
;
; ================================================
; Derived constants
; ================================================
;
.EQU cR2c = (cR2 * cRin) / (cR2+cRin)
.EQU cMultiplier = (641 * (cR1+cR2c))/cR2c ; used for voltage multiplication
.EQU cMaxVoltage = 1024*cMultiplier/256 ; in mV
.EQU cSafeVoltage = (cMaxVoltage * 5000) / 2560
.EQU cTDiv = 1000/nMeasm ; interval per measurement update
; calculating the CTC and prescaler values for TC1 (frequency measurement)
.SET cCmp1F = cFreq/32 ; CTC compare value with counter prescaler = 8
.SET cPre1F = (1<<WGM12)|(1<<CS11) ; CTC and counter prescaler = 8
.IF cFreq>2097120
.SET cCmp1F = cFreq/256 ; CTC compare value with counter prescaler = 64
.SET cPre1F = (1<<WGM12)|(1<<CS11)|(1<<CS10) ; counter prescaler = 64
.ENDIF
.IF cFreq>16776960
.SET cCmp1F = cFreq/1024 ; CTC compare value with counter prescaler = 256
.SET cPre1F = (1<<WGM12)|(1<<CS12) ; counter prescaler = 256
.ENDIF
; calculating the CTC and counter prescaler values for TC2 (LCD/UART update)
.SET cCmp2 = cFreq/8000
.SET cPre2 = (1<<CS21) ; counter prescaler = 8
.IF cFreq>2040000
.SET cCmp2 = cFreq/32000
.SET cPre2 = (1<<CS21)|(1<<CS20) ; counter prescaler = 32
.ENDIF
.IF cFreq>8160000
.SET cCmp2 = cFreq/64000
.SET cPre2 = (1<<CS22) ; counter prescaler = 64
.ENDIF
.IF cFreq>16320000
.SET cCmp2 = cFreq/128000 ; counter prescaler = 128
.SET cPre2 = (1<<CS22)|(1<<CS20)
.ENDIF
;
; Uart constants
;
.IF cUart
.EQU cNul = $00
.EQU cClrScr = $0C
.EQU cCr = $0D
.EQU cLf = $0A
.ENDIF
;
; Debug definitions for testing
;
; (none)
;
; ================================================
; Register definitons
; ================================================
;
; R0 used for LPM and for calculation purposes
.DEF rRes1 = R1 ; Result byte 1
.DEF rRes2 = R2 ; Result byte 2
.DEF rRes3 = R3 ; Result byte 3
.DEF rRes4 = R4 ; Result byte 4
.DEF rDiv1 = R5 ; Divisor byte 1
.DEF rDiv2 = R6 ; Divisor byte 2
.DEF rDiv3 = R7 ; Divisor byte 3
.DEF rDiv4 = R8 ; Divisor byte 4
.DEF rCpy1 = R9 ; Copy byte 1
.DEF rCpy2 = R10 ; Copy byte 2
.DEF rCpy3 = R11 ; Copy byte 3
.DEF rCpy4 = R12 ; Copy byte 4
.DEF rCtr1 = R13 ; Counter/Timer byte 1
.DEF rCtr2 = R14 ; Counter/Timer byte 2
.DEF rCtr3 = R15 ; Counter/Timer byte 3
.DEF rmp = R16 ; Multipurpose register outside interrupts
.DEF rimp = R17 ; Multipurpose register inside interrupts
.DEF rSreg = R18 ; Save status register inside interrupts
.DEF rTDiv = R19 ; Internal divider for TC2 count down
.DEF rMode = R20 ; Current mode of operation
.DEF rNMode = R21 ; Number of inadequate measurements
.DEF rir = R22 ; interrim calculation register
.DEF rFlg = R23 ; Flag register
.EQU bCyc = 2 ; measure cycle ended
.EQU bMode = 3 ; measuring mode, 1 = frequency, 0 = time
.EQU bEdge = 4 ; measured edge, 1 = rising, 0 = falling
.EQU bOvf = 5 ; overflow bit
.EQU bAdc = 6 ; ADC conversion complete flag bit
.EQU bUartRxLine = 7 ; Uart line complete flag bit
.DEF rDelL = R24 ; delay counter for LCD, LSB
.DEF rDelH = R25 ; dto., MSB
; X = R26..R27 used for calculation purposes
; Y = R28..R29: free
; Z = R30..R31 used for LPM and calculation purposes
;
; ================================================
; SRAM definitions
; ================================================
;
.DSEG
.ORG Sram_Start
;
; Result display space in SRAM
;
sResult:
.BYTE 32
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
;
.IF cUart
.EQU UartRxbLen = 38 ; Buffer length in bytes
;
sUartFlag: ; flag register for Uart
.BYTE 1
.EQU bUMonU = 0 ; displays voltage over Uart
.EQU bUMonF = 1 ; displays frequency over Uart
; free: bits 2..7
sUartMonUCnt: ; counter for Monitoring voltage
.BYTE 1
sUartMonURpt: ; counter preset for monitoring voltage
.BYTE 1
sUartMonFCnt: ; counter for Monitoring frequency
.BYTE 1
sUartMonFRpt: ; counter preset for monitoring voltage
.BYTE 1
sUartRxBp: ; buffer pointer
.BYTE 1
sUartRxBs: ; buffer
.BYTE UartRxbLen
sUartRxBe: ; buffer end
.ENDIF
;
; Main interval timer characteristics
;
sTMeas: ; ms per measuring interval (default: 250)
.BYTE 1
;
; ADC result
;
sAdc0L: ; ADC result, channel 0, LSB
.BYTE 1
sAdc0H: ; ADC result, channel 0, MSB
.BYTE 1
sAdc1L: ; ADC result, channel 1, LSB
.BYTE 1
sAdc1H: ; ADC result, channel 1, MSB
.BYTE 1
;
; Interim storage for counter value during time measurement
;
sCtr:
.BYTE 4
;
; ================================================
; Selected mode flags
; ================================================
;
; Mode Measuring Prescale Display
; ---------------------------------------------
; 0 Frequency 16 Frequency
; 1 Frequency 1 Frequency
; 2 Time HL 1 Frequency
; 3 Time HL 1 Rounds per Minute
; 4 Time HL 1 Time
; 5 Time H 1 Time
; 6 Time L 1 Time
; 7 PW ratio H 1 Pulse width ratio H %
; 8 PW ratio L 1 Pulse width ratio L %
; 9 none - Voltage only
; (for a single line LCD)
;
.EQU cModeFrequency16 = 0
.EQU cModeFrequency = 1
.EQU cModeTimeFreq = 2
.EQU cModeTimeRpm = 3
.EQU cModeTimeTimeHL = 4
.EQU cModeTimeTimeH = 5
.EQU cModeTimeTimeL = 6
.EQU cModeTimePwrH = 7
.EQU cModeTimePwrL = 8
.EQU cModeVoltage = 9
;
sModeSlct: ; Selected mode
.BYTE 1
sModeNext: ; next selected mode
.BYTE 1
;
; ==================================================
; Info on timer and counter interrupt operation
; ==================================================
;
; Clock => Presc2 => TC2 => CTC => rTDiv =>
; ADC0 conversion => ADC1 conversion => bAdc-flag
;
; Main interval timer TC2
; - uses TC2 as 8-bit-CTC, with compare interrupt
; - starts a ADC conversion
; - on ADC conversion complete:
; * store ADC result
; * convert ADC result
; * if a new counter result: convert this
; * if Uart connected and monitoring f/U: display on Uart
; * if LCD connected and display mode: display f/U result
;
; Operation at 16 MHz clock:
; cFreq => Prescaler/128 => CTC(125) => rTDiv(250)
; 16MHz => 125 kHz => 1 kHz => 4 Hz
;
; Frequeny counting modes (Mode = 0 and 1)
; - uses TC0 as 8-bit-counter to count positive edges
; - uses TC1 as 16-bit-counter to time-out the counter after 250 ms
;
; Timer modes (Mode = 2 to 8)
; - uses edge detection on external INT0 for timeout
; - uses TC1 as 16-bit-counter to time-out from edge to edge
;
; Voltage only (Mode = 9)
; - Timers TC0 and TC1 off
; - Timer TC2 times interval
;
; ==============================================
; Reset and Interrupt Vectors starting here
; ==============================================
;
.CSEG
.ORG $0000
;
; Reset/Intvectors
;
rjmp Main ; Reset
rjmp Int0Int; Int0
reti ; Int1
rjmp TC2CmpInt ; TC2 Comp
reti ; TC2 Ovf
reti ; TC1 Capt
rjmp Tc1CmpAInt ; TC1 Comp A
reti ; TC1 Comp B
rjmp Tc1OvfInt ; TC1 Ovf
rjmp TC0OvfInt ; TC0 Ovf
reti ; SPI STC
.IF cUart
rjmp SioRxcIsr ; USART RX
.ELSE
reti ; USART RX
.ENDIF
reti ; USART UDRE
reti ; USART TXC
rjmp AdcCcInt ; ADC Conv Compl
reti ; EERDY
reti ; ANA_COMP
reti ; TWI
reti ; SPM_RDY
;
; =============================================
;
; Interrupt Service Routines
;
; =============================================
;
; TC2 Compare Match Interrupt
; counts rTDiv down, if zero: starts an AD conversion
;
TC2CmpInt:
in rSreg,SREG ; save SREG
dec rTDiv ; count down
brne TC2CmpInt1 ; not zero, interval not ended
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start ADC conversion
lds rTDiv,sTMeas ; restart interval timer
TC2CmpInt1:
out SREG,rSreg ; restore SREG
reti
;
; External Interrupt INT0 Service Routine
; active in modes 2 to 6 (measuring the signal duration),
; detects positive going edges of the input
; INT1, TC1 is in free running mode,
; reads the current counter state of TC1,
; copies it to the result registers,
; clears the counter and restarts it
;
Int0Int:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp Int0Int1 ; 4, no, last result hasn't been read
in rCpy1,TCNT1L ; 4, read timer 1 LSB
in rCpy2,TCNT1H ; 5, dto., MSB
mov rCpy3,rCtr2 ; 6, copy the counter bytes
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
cbr rFlg,1<<bEdge ; 9, set falling edge
sbic PIND,2 ; 10/11, check if input = 0
sbr rFlg,1<<bEdge ; 11, no, set edge flag to rising
Int0Int1: ; 4/11
ldi rimp,0 ; 5/12, reset the timer
out TCNT1H,rimp ; 6/13, set TC1 zero to restart
out TCNT1L,rimp ; 7/14
mov rCtr1,rimp ; 8/15, clear the upper bytes
mov rCtr2,rimp ; 9/16
mov rCtr3,rimp ; 10/17
out SREG,rSreg ; 11/18, restore SREG
reti ; 15/22
;
; TC1 Compare Match A Interrupt Service Routine
; active in modes 0 and 1 (measuring the number of
; sigals on the T1 input), timeout every 0.25s,
; reads the counter TC0, copies the count to
; the result registers and clears TC0
;
Tc1CmpAInt:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp TC1CmpAInt1 ; 4, no, last result hasn't been read
in rCpy1,TCNT0 ; 4, read counter TC0
mov rCpy2,rCtr1 ; 5, copy counter bytes to result
mov rCpy3,rCtr2 ; 6
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
Tc1CmpAInt1: ; 4/8
ldi rimp,0 ; 5/9, clear counter
out TCNT0,rimp ; 6/10
mov rCtr1,rimp ; 7/11, clear counter bytes
mov rCtr2,rimp ; 8/12
mov rCtr3,rimp ; 9/13
out SREG,rSreg ; 10/14, restore SREG
reti ; 14/18
;
; TC1 Overflow Interrupt Service Routine
; active in modes 2 to 6 counting clock cycles to measure time
; increases the upper bytes and detects overflows
;
Tc1OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr2 ; 2, increase byte 3 of the counter
brne Tc1OvfInt1 ; 3/4, no overflow
inc rCtr3 ; 4, increase byte 4 of the counter
brne Tc1OvfInt1 ; 5/6, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 6, set overflow and end of cycle bit
Tc1OvfInt1: ; 4/6
out SREG,rSreg ; 5/7, restore SREG
reti ; 9/11
;
; TC0 Overflow Interrupt Service Routine
; active in modes 0 and 1 counting positive edges on T1
; increases the upper bytes and detects overflows
;
Tc0OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr1 ; 2, increase byte 2 of the counter
brne Tc0OvfInt1 ; 3/4, no overflow
inc rCtr2 ; 4, increase byte 3 of the counter
brne Tc0OvfInt1 ; 5/6, no overflow
inc rCtr3 ; 6, increase byte 4 of the counter
brne Tc0OvfInt1 ; 7/8, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 8, set overflow bit
Tc0OvfInt1: ; 4/6/8
out SREG,rSreg ; 5/7/9, restore SREG
reti ; 9/11/13
;
; Uart RxC Interrupt Service Routine
; receives a character, signals errors, echoes it back,
; puts it into the SRAM line buffer, checks for carriage
; return characters, if yes echoes additional linefeed
; and sets line-complete flag
;
.IF cUart
SioRxCIsr:
in rSreg,SREG ; 1, Save SReg
in rimp,UCSRA ; 2, Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; 3, isolate error bits
in rimp,UDR ; 4, read character from UART
breq SioRxCIsr1 ; 5/6, no errors
ldi rimp,'*' ; 6, signal an error
out UDR,rimp ; 7
rjmp SioRxCIsr4 ; 9, return from int
SioRxCIsr1: ; 6
out UDR,rimp ; 7, echo the character
push ZH ; 9, Save Z register
push ZL ; 11
ldi ZH,HIGH(sUartRxBs) ; 12, Load Position for next RX char
lds ZL,sUartRxBp ; 14
st Z+,rimp ; 16, save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; 17, End of buffer?
brcc SioRxCIsr2 ; 18/19, Buffer overflow
sts sUartRxBp,ZL ; 20, Save next pointer position
SioRxCIsr2: ; 19/20
cpi rimp,cCr ; 20/21, Carriage Return?
brne SioRxCIsr3 ; 21/22/23, No, go on
ldi rimp,cLf ; 22/23, Echo linefeed
out UDR,rimp ; 23/24
sbr rFlg,(1<<bUartRxLine) ; 24/25, Set line complete flag
rjmp SioRxCIsr3a
SioRxCIsr3: ; 22/23/24/25
cpi rimp,cLf
brne SioRxCIsr3a
sbr rFlg,(1<<bUartRxLine)
SioRxCIsr3a:
pop ZL ; 24/25/26/27, restore Z-register
pop ZH ; 26/27/28/29
SioRxCIsr4: ; 9/26/27/28/29
out SREG,rSreg ; 10/27/28/29/30, restore SREG
reti ; 14/31/32/33/34, return from Int
.ENDIF
;
; ADC has completed a conversion
; used in all modes, ADC has completed a conversion
; if ADMUX channel is 0 then set ADMUX=1 and start
; another coversion
; if ADMUX channel is 1 he set ADMUX=0, disable the ADC
; and set teh ADC cycle end flag
;
.EQU cStopAdc = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
.EQU cStartAdc = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|cStopAdc
AdcCcInt:
in rSreg,SREG ; 1, save SREG
in rimp,ADMUX ; 2, read the current channel info
sbrc rimp,0 ; 3/4, jump if channel = 0
rjmp AdcCcInt1 ; 5
sbr rimp,1 ; 5, set channel MUX to one
out ADMUX,rimp ; 6
in rimp,ADCL ; 7, read result LSB
sts sAdc0L,rimp ; 9, store result LSB
in rimp,ADCH ; 10, read result MSB
sts sAdc0H,rimp ; 12, store result MSB
ldi rimp,cStartAdc
out ADCSRA,rimp ; 14, start next conversion
out SREG,rSreg ; 15, restore SREG
reti ; 19
AdcCcInt1: ; 5
cbr rimp,1 ; 6, set MUX to channel 0
out ADMUX,rimp ; 7
in rimp,ADCL ; 8, read result LSB
sts sAdc1L,rimp ; 10, store result LSB
in rimp,ADCH ; 11, read result MSB
sts sAdc1H,rimp ; 13, store result MSB
sbr rFlg,1<<bAdc ; 14, set flag bit
ldi rimp,cStopAdc ; 15, ADC off
out ADCSRA,rimp ; 16, switch ADC off
out SREG,rSreg ; 17, restore SREG
reti ; 21
;
; ================================================
; Common subroutines
; ================================================
;
; Setting timer/counter modes for measuring
;
SetModeNext:
rcall ClrTc ; clear the timers TC0 and TC1, disable INT0
lds rmp,sModeNext ; read next mode
mov rMode,rmp ; copy to current mode
ldi ZH,HIGH(SetModeTab)
ldi ZL,LOW(SetModeTab)
add ZL,rmp
ldi rmp,0
adc ZH,rmp
ijmp
; Table mode setting
SetModeTab:
rjmp SetMode0 ; f div 16, f
rjmp SetMode1 ; f, f
rjmp SetModeT ; t, f
rjmp SetModeT ; t, u
rjmp SetModeT ; t, t
rjmp SetModeE ; th, t
rjmp SetModeE ; tl, t
rjmp SetModeE ; th, p
rjmp SetModeE ; tl, p
ret ; U, U
;
; Set counters/timers to mode 0
; TC0 counts input signals (positive edges)
; TC1 times the gate at 250 ms
; INT0 disabled
;
SetMode0:
cbi pPresc,bPresc ; enable prescaler
rjmp SetModeF ; frequency measurement
;
; Set counters/timers to mode 1
;
SetMode1:
sbi pPresc,bPresc ; disable prescaler
; Set timer/counter mode to frequency measurement
SetModeF:
ldi rmp,HIGH(cCmp1F) ; set the compare match high value
out OCR1AH,rmp
ldi rmp,LOW(cCmp1F) ; set the compare match low value
out OCR1AL,rmp
ldi rmp,0xFF ; disable the compare match B
out OCR1BH,rmp
out OCR1BL,rmp
ldi rmp,0 ; CTC mode
out TCCR1A,rmp
ldi rmp,cPre1F ; set the prescaler value for TC1
out TCCR1B,rmp
ldi rmp,(1<<CS02)|(1<<CS01)|(1<<CS00) ; count rising edges on T0
out TCCR0,rmp
ldi rmp,(1<<OCIE2)|(1<<OCIE1A)|(1<<TOIE0) ; enable TC2Cmp, TC1CmpAInt and
TC0OverflowInt
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement
;
SetModeT:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00) ; sleep enable, positive edges on INT0 interrupt
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement, all edges
;
SetModeE:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC00) ; sleep enable, any logical change on INT0 interrupts
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
;
; clears the timers and resets the upper bytes
;
ClrTc:
clr rmp ; disable INT0
out GICR,rmp
clr rmp ; stop the counters/timers
out TCCR0,rmp ; stop TC0 counting/timing
out TCCR1B,rmp ; stop TC1 counting/timing
out TCNT0,rmp ; clear TC0
out TCNT1L,rmp ; clear TC1
out TCNT1H,rmp
clr rCtr1 ; clear upper bytes
clr rCtr2
clr rCtr3
ldi rmp,1<<OCIE2 ; enable only output compare of TC2 ints
out TIMSK,rmp ; timer int disable
ret
;
; =======================================================
; Math routines
; =======================================================
;
; Divides cFreq/256 by the timer value in rDiv4:rDiv3:rDiv2:rDiv1
; yields frequency in R4:R3:R2:(Fract):R1
;
Divide:
clr rmp ; rmp:R0:ZH:ZL:XH:XL is divisor
clr R0
clr ZH
ldi ZL,BYTE3(cFreq/256) ; set divisor
ldi XH,BYTE2(cFreq/256)
ldi XL,BYTE1(cFreq/256)
clr rRes1 ; set result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
Divide1:
lsl XL ; multiply divisor by 2
rol XH
rol ZL
rol ZH
rol R0
rol rmp
cp ZL,rDiv1 ; compare with divident
cpc ZH,rDiv2
cpc R0,rDiv3
cpc rmp,rDiv4
brcs Divide2
sub ZL,rDiv1
sbc ZH,rDiv2
sbc R0,rDiv3
sbc rmp,rDiv4
sec
rjmp Divide3
Divide2:
clc
Divide3:
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc Divide1
ret
;
; Multiply measured time in rRes4:rRes3:rRes2:rRes1 by 65536 / fq(MHz)
; rmp:R0 are the upper bytes of the input
; ZH:ZL:rDiv4:rDiv3:rDiv2:rDiv1 is the interim result
; XH:XL is the multiplicator
; result is in rRes4:rRes3:rRes2:rRes1
;
.EQU cMulti = 65536000 / (cFreq/1000)
;
Multiply:
ldi XH,HIGH(cMulti) ; set multiplicator
ldi XL,LOW(cMulti)
clr ZH
clr ZL
clr rDiv4
clr rDiv3
clr rDiv2
clr rDiv1
clr R0
clr rmp
Multiply1:
cpi XL,0
brne Multiply2
cpi XH,0
breq Multiply4
Multiply2:
lsr XH
ror XL
brcc Multiply3
add rDiv1,rRes1
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
adc ZL,R0
adc ZH,rmp
Multiply3:
lsl rRes1
rol rRes2
rol rRes3
rol rRes4
rol R0
rol rmp
rjmp Multiply1
Multiply4:
ldi rmp,128 ; round result
clr R0
add rDiv2,rmp
adc rDiv3,R0
adc rDiv4,R0
adc ZL,R0
adc ZH,R0
mov rRes1,rDiv3 ; move result
mov rRes2,rDiv4
mov rRes3,ZL
mov rRes4,ZH
ret
;
; Display seconds at buffer end
;
DisplSec:
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'u'
st X+,rmp
ldi rmp,'s'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ret
;
; An overflow has occurred during pulse width calculation
;
PulseOvflw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
st X+,rmp
.IF cDisplay8
ldi ZH,HIGH(2*TxtPOvflw8)
ldi ZL,LOW(2*TxtPOvflw8)
ldi rmp,7
.ELSE
ldi ZH,HIGH(2*TxtPOvflw16)
ldi ZL,LOW(2*TxtPOvflw16)
ldi rmp,15
.ENDIF
PulseOvflw1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne PulseOvflw1
ret
.IF cDisplay8
TxtPOvflw8:
.DB ":error! "
.ELSE
TxtPOvflw16:
.DB ":error calcul.! "
.ENDIF
;
; ======================================================
; Pulse width calculations
; ======================================================
;
; Calculate the pulse width ratio
; active cycle time is in rDelH:rDelL:R0:rmp
; total cycle time is in rDiv
; result will be in rRes
; overflow: carry flag is set
;
CalcPwO: ; overflow
sec
ret
CalcPw:
mov rRes1,rmp ; copy active cycle time to rRes
mov rRes2,R0
mov rRes3,rDelL
mov rRes4,rDelH
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
mov XL,rRes1 ; copy to Z:X
mov XH,rRes2
mov ZL,rRes3
mov ZH,rRes4
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO
add rRes1,XL ; * 24
adc rRes2,XH
adc rRes3,ZL
adc rRes4,ZH
clr ZH ; clear the four MSBs of divisor
clr ZL
clr XH
mov XL,rDelH ; * 256
mov rDelH,rDelL
mov rDelL,R0
mov R0,rmp
clr rmp
lsl R0 ; * 512
rol rDelL
rol rDelH
rol XL
rol XH
lsl R0 ; * 1024
rol rDelL
rol rDelH

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm (1 of 4)1/20/2009 7:40:33 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm

rol XL
rol XH
sub rmp,rRes1 ; * 1000
sbc R0,rRes2
sbc rDelL,rRes3
sbc rDelH,rRes4
sbc XL,ZH
sbc XH,ZH
cp XL,rDiv1 ; overflow?
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcc CalcPwO
clr rRes1 ; clear result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
CalcPw1: ; dividing loop
lsl rmp ; multiply by 2
rol R0
rol rDelL
rol rDelH
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1 ; compare with divisor
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw2 ; smaller, roll zero in
sub XL,rDiv1 ; subtract divisor
sbc XH,rDiv2
sbc ZL,rDiv3
sbc ZH,rDiv4
sec ; roll one in
rjmp CalcPw3
CalcPw2:
clc
CalcPw3: ; roll result
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc CalcPw1 ; roll on
lsl rDelL ; round result
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw4
ldi rmp,1 ; round up
add rRes1,rmp
ldi rmp,0
adc rRes2,rmp
adc rRes3,rmp
adc rRes4,rmp
CalcPw4:
tst rRes4 ; check > 1000
brne CalcPwE
tst rRes3
brne CalcPwE
ldi rmp,LOW(1001)
cp rRes1,rmp
ldi rmp,HIGH(1001)
cpc rRes2,rmp
brcc CalcPwE
clc ; no error
ret
CalcPwE: ; error
sec
ret
;
; Display the binary in R2:R1 in the form " 100,0%"
;
DisplPw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
ldi rmp,' '
st X+,rmp
st X+,rmp
clr R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecX2
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall DisplDecX2
ldi ZL,10
inc R0
rcall DisplDecX2
ldi rmp,cDecSep
st X+,rmp
ldi rmp,'0'
add rmp,rRes1
st X+,rmp
ldi rmp,'%'
st X+,rmp
.IF ! cDisplay8
ldi rmp,8
ldi ZL,' '
DisplPw1:
st X+,ZL
dec rmp
brne DisplPw1
.ENDIF
ret
;
; If the first characters in the result buffer are empty,
; place the character in ZL here and add equal, if possible
;
DisplMode:
ldi XH,HIGH(sResult+1) ; point to result buffer
ldi XL,LOW(sResult+1)
ld rmp,X ; read second char
cpi rmp,' '
brne DisplMode1
ldi rmp,'='
st X,rmp
DisplMode1:
sbiw XL,1
ld rmp,X ; read first char
cpi rmp,' '
brne DisplMode2
st X,ZL
DisplMode2:
ret
;
;=================================================
; Display binary numbers as decimal
;=================================================
;
; Converts a binary in R2:R1 to a digit in X
; binary in Z
;
DecConv:
clr rmp
DecConv1:
cp R1,ZL ; smaller than binary digit?
cpc R2,ZH
brcs DecConv2 ; ended subtraction
sub R1,ZL
sbc R2,ZH
inc rmp
rjmp DecConv1
DecConv2:
tst rmp
brne DecConv3
tst R0
brne DecConv3
ldi rmp,' ' ; suppress leading zero
rjmp DecConv4
DecConv3:
subi rmp,-'0'
DecConv4:
st X+,rmp
ret
;
; Display fractional number in R3:R2:(Fract)R1
;
DisplFrac:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
.ENDIF
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DisplDecY2
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecY2
.IF ! cDisplay8
ldi rmp,c1kSep
tst R0
brne DisplFrac0
ldi rmp,' '
DisplFrac0:
st X+,rmp
.ENDIF
ldi ZL,100
rcall DisplDecY1
ldi ZL,10
rcall DisplDecY1
ldi rmp,'0'
add rmp,R2
st X+,rmp
tst R1 ; fraction = 0?
brne DisplFrac1
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
st X+,rmp
st X+,rmp
.ENDIF
ret
DisplFrac1:
ldi rmp,cDecSep
st X+,rmp
.IF cDisplay8
ldi ZL,2
.ELSE
ldi ZL,3
.ENDIF
DisplFrac2:
clr rRes3
clr rRes2
mov R0,rRes1 ; * 1
lsl rRes1 ; * 2
adc rRes2,rRes3
lsl rRes1 ; * 4
rol rRes2
add rRes1,R0 ; * 5
adc rRes2,rRes3
lsl rRes1 ; * 10
rol rRes2
ldi rmp,'0'
add rmp,rRes2
st X+,rmp
dec ZL
brne DisplFrac2
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X+,rmp
.ENDIF
ret
;
; Convert a decimal in R4:R3:R2, decimal in ZH:ZL
;
DisplDecY2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY2a:
cp rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecY2b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecY2a
DisplDecY2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY2c
ldi rmp,' '
DisplDecY2c:
st X+,rmp
ret
;
; Convert a decimal decimal in R:R2, decimal in ZL
;
DisplDecY1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY1a:
cp rRes2,ZL
cpc rRes3,rDiv2
brcs DisplDecY1b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecY1a
DisplDecY1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY1c
ldi rmp,' '
DisplDecY1c:
st X+,rmp
ret
;
; Display a 4-byte-binary in decimal format on result line 1
; 8-bit-display: "12345678"
; 16-bit-display: " 12.345.678 Hz "
;
Displ4Dec:
ldi rmp,BYTE1(100000000) ; check overflow
cp rRes1,rmp
ldi rmp,BYTE2(100000000)
cpc rRes2,rmp
ldi rmp,BYTE3(100000000)
cpc rRes3,rmp
ldi rmp,BYTE4(100000000)
cpc rRes4,rmp
brcs Displ4Dec1
rjmp CycleOvf
Displ4Dec1:
clr R0 ; suppress leading zeroes
ldi XH,HIGH(sResult) ; X to result buffer
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' ' ; clear the first two digits
st X+,rmp
st X+,rmp
.ENDIF
ldi ZH,BYTE3(10000000) ; 10 mio
ldi ZL,BYTE2(10000000)
ldi rmp,BYTE1(10000000)
rcall DisplDecX3
ldi ZH,BYTE3(1000000) ; 1 mio
ldi ZL,BYTE2(1000000)
ldi rmp,BYTE1(1000000)
rcall DisplDecX3
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec2
ldi rmp,' '
Displ4Dec2:
st X+,rmp
.ENDIF
ldi ZH,BYTE3(100000) ; 100 k
ldi ZL,BYTE2(100000)
ldi rmp,BYTE1(100000)
rcall DisplDecX3
ldi ZH,HIGH(10000) ; 10 k
ldi ZL,LOW(10000)
rcall DisplDecX2
ldi ZH,HIGH(1000) ; 1 k
ldi ZL,LOW(1000)
rcall DisplDecX2
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec3
ldi rmp,' '
Displ4Dec3:
st X+,rmp
.ENDIF
ldi ZL,100 ; 100
rcall DisplDecX1
ldi ZL,10
rcall DisplDecX1
ldi rmp,'0' ; 1
add rmp,R1
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL:rmp
;
DisplDecX3:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; subtractor for byte 4
DisplDecX3a:
cp rRes1,rmp ; compare
cpc rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecX3b ; ended
sub rRes1,rmp ; subtract
sbc rRes2,ZL
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecX3a
DisplDecX3b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX3c
ldi rmp,' '
DisplDecX3c:
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL
;
DisplDecX2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX2a:
cp rRes1,ZL
cpc rRes2,ZH
cpc rRes3,rDiv2
brcs DisplDecX2b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,ZH
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecX2a
DisplDecX2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX2c
ldi rmp,' '
DisplDecX2c:
st X+,rmp
ret
;
; Convert a decimal in R2:R1, decimal in ZL
;
DisplDecX1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX1a:
cp rRes1,ZL
cpc rRes2,rDiv2
brcs DisplDecX1b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,rDiv2
inc rDiv1
rjmp DisplDecX1a
DisplDecX1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX1c
ldi rmp,' '
DisplDecX1c:
st X+,rmp
ret
;
;=================================================
; Delay routines
;=================================================
;
Delay10ms:
ldi rDelH,HIGH(10000)
ldi rDelL,LOW(10000)
rjmp DelayZ
Delay15ms:
ldi rDelH,HIGH(15000)
ldi rDelL,LOW(15000)
rjmp DelayZ
Delay4_1ms:
ldi rDelH,HIGH(4100)
ldi rDelL,LOW(4100)
rjmp DelayZ
Delay1_64ms:
ldi rDelH,HIGH(1640)
ldi rDelL,LOW(1640)
rjmp DelayZ
Delay100us:
clr rDelH
ldi rDelL,100
rjmp DelayZ
Delay40us:
clr rDelH
ldi rDelL,40
rjmp DelayZ
;
; Delays execution for Z microseconds
;
DelayZ:
.IF cFreq>18000000
nop
nop
.ENDIF
.IF cFreq>16000000
nop
nop
.ENDIF
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
sbiw rDelL,1 ; 2
brne DelayZ ; 2
ret
;
; =========================================
; Main Program Start
; =========================================
;
main:
ldi rmp,HIGH(RAMEND) ; set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
clr rFlg ; set flags to default
;
.IF debug
.EQU number = 100000000
ldi rmp,BYTE4(number)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(number)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(number)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(number)
mov rRes1,rmp
mov rDiv1,rmp
rcall CycleM6
beloop: rjmp beloop
.ENDIF
.IF debugpulse
.EQU nhigh = 100000000
.EQU nlow = 15000
ldi rmp,BYTE4(nhigh)
sts sCtr+3,rmp
ldi rmp,BYTE3(nhigh)
sts sCtr+2,rmp
ldi rmp,BYTE2(nhigh)
sts sCtr+1,rmp
ldi rmp,BYTE1(nhigh)
sts sCtr,rmp
ldi rmp,BYTE4(nlow)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(nlow)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(nlow)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(nlow)
mov rRes1,rmp
mov rDiv1,rmp
sbr rFlg,1<<bEdge
rcall CycleM7
bploop: rjmp bploop
.ENDIF
;
; Clear the output storage
;
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,' '
mov R0,rmp
ldi rmp,32
main1:
st Z+,R0
dec rmp
brne main1
;
; Init the Uart
;
.IF cUart
rcall UartInit
ldi rmp,1<<bUMonU ; monitor U over Uart
sts sUartFlag,rmp
ldi rmp,20 ; 5 seconds
sts sUartMonURpt,rmp ; set repeat default value
ldi rmp,1
sts sUartMonUCnt,rmp
ldi rmp,4 ; 1 seconds
sts sUartMonFCnt,rmp
.ENDIF
;
; Init the LCD
;
.IF cDisplay
rcall LcdInit
.ENDIF
;
; Disable the Analog comparator
;
ldi rmp,1<<ACD
out ACSR,rmp
;
; Disable the external prescaler by 16
;
sbi pPrescD,bPresc ; set prescaler port bit to output
sbi pPresc,bPresc ; disable the prescaler
;
; Init the ADC
;
ldi rmp,(1<<REFS1)|(1<<REFS0) ; int.ref, channel 0
out ADMUX,rmp
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; prescaler = 128
out ADCSRA,rmp
;
; Start main interval timer
;
ldi rmp,cCmp2 ; set Compare Match
out OCR2,rmp
ldi rmp,cPre2|(1<<WGM21) ; CTC mode and prescaler
out TCCR2,rmp
;
; Start timer/counter TC2 interrupts
;
ldi rmp,(1<<OCIE2) ; Interrupt mask
out TIMSK,rmp
;
; Set initial mode to mode 1
;
ldi rmp,1 ; initial mode = 1
sts sModeNext,rmp
rcall SetModeNext
;
sei ; enable interrupts
;
loop:
sleep ; send CPU to sleep
nop
sbrc rFlg,bCyc ; check cycle end
rcall Cycle
sbrc rFlg,bAdc
rcall Interval
.IF cUart
sbrc rFlg,bUartRxLine ; check line complete
rcall UartRxLine ; call line complete
.ENDIF
rjmp loop ; go to sleep
;
; Timer interval for calculation and display
;
Interval:
cbr rFlg,1<<bAdc ; clear flag
lds ZL,sAdc1L ; read ADC channel 1 value
lds ZH,sAdc1H
mov XL,ZL ; copy to X
mov XH,ZH
lsl ZL ; multiply by 2
rol ZH
lsl ZL ; multiply by 4
rol ZH
add ZL,XL ; multiply by 5
adc ZH,XH
lsr ZH ; multiply by 2.5
ror ZL
cpi ZH,10 ; larger than 9?
brcs Interval1
ldi ZH,9 ; set to 9
Interval1:
sts sModeNext,ZH ; store next mode
cp rMode,ZH ; new mode?
breq Interval2 ; continue current mode
rcall SetModeNext ; start new mode
Interval2:
.IF cUart || cDisplay
lds R0,sAdc0L ; read ADC value
lds R1,sAdc0H
rcall cAdc2U ; convert to text
.IF cDisplay
rcall LcdDisplayFT
rcall LcdDisplayU
.ENDIF
.IF cUart
rcall UartMonU
.ENDIF
.ENDIF
ret
;
; Frequency/Time measuring cycle ended, calculate results
;
Cycle:
sbrc rFlg,bOvf ; check overflow
rjmp CycleOvf ; jump to overflow
mov rRes1,rCpy1 ; copy counter
mov rRes2,rCpy2
mov rRes3,rCpy3
mov rRes4,rCpy4
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
mov rDiv1,rRes1 ; copy again
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
.IF cUart
ldi ZH,HIGH(UartMonF) ; put monitoring frequency on stack
ldi ZL,LOW(UartMonF)
push ZL
push ZH
.ENDIF
ldi ZH,HIGH(CycleTab) ; point to mode table
ldi ZL,LOW(CycleTab)
add ZL,rMode ; displace table by mode
brcc Cycle1
inc ZH
Cycle1:
ijmp ; call the calculation routine
; overflow occurred
CycleOvf:
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
ldi XH,HIGH(sResult) ; point to result buffer
ldi XL,LOW(sResult)
.IF cDisplay8
ldi ZH,HIGH(2*TxtOvf8) ; point to short message
ldi ZL,LOW(2*TxtOvf8)
ldi rmp,8
.ELSE
ldi ZH,HIGH(2*TxtOvf16) ; point to long message
ldi ZL,LOW(2*TxtOvf16)
ldi rmp,16
.ENDIF
CycleOvf1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne CycleOvf1
ret
;
.IF cDisplay8
TxtOvf8:
.DB " ovflow"
.ELSE
TxtOvf16:
.DB " overflow "
.ENDIF
; Table with routines for the 8 modes
CycleTab:
rjmp CycleM0
rjmp CycleM1
rjmp CycleM2
rjmp CycleM3
rjmp CycleM4
rjmp CycleM5
rjmp CycleM6
rjmp CycleM7
rjmp CycleM8
ret ; voltage only
;
; Mode 0: Measured prescaled frequency, display frequency
;
CycleM0:
clr R5 ; for detecting an overflow in R5
lsl R1 ; * 2
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 4
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 8
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 16
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 32
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 64
rol R2
rol R3
rol R4
rol R5
tst R5 ; check overflow
breq CycleM0a ; no error
rjmp CycleOvf
CycleM0a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'F'
rjmp DisplMode
;
; Mode 1: Frequency measured, prescale = 1, display frequency
;
CycleM1:
clr rDiv1 ; detect overflow in rDiv1
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
tst rDiv1 ; check overflow
breq CycleM1a ; no error
rjmp CycleOvf
CycleM1a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'f'
rjmp DisplMode
;
; Mode 2: Time measured, prescale = 1, display frequency
;
CycleM2:
rcall Divide
tst rRes4
brne CycleM2a
rcall DisplFrac
ldi ZL,'v'
rcall DisplMode
ret
CycleM2a:
mov rRes1,rRes2 ; number too big, skip fraction

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm (2 of 4)1/20/2009 7:40:33 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm

mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'v'
rcall DisplMode
ret
;
; Measure time, display rounds per minute
;
CycleM3:
rcall Divide
clr R0 ; overflow detection
clr rmp
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
mov rDiv1,rRes1 ; copy
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 32
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 64
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
tst R0 ; overflow?
breq CycleM3a
rjmp CycleOvf
CycleM3a:
sub rRes1,rDiv1
sbc rRes2,rDiv2
sbc rRes3,rDiv3
sbc rRes4,rDiv4
mov rRes1,rRes2
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'r'
st X+,rmp
ldi rmp,'p'
st X+,rmp
ldi rmp,'m'
st X+,rmp
.ENDIF
ldi ZL,'u'
rcall DisplMode
ret
;
; Measure time high+low, display time
;
CycleM4:
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'t'
rcall DisplMode
ret
;
; Measure time high, display time
;
CycleM5:
sbrs rFlg,bEdge
rjmp CycleM5a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'h'
rcall DisplMode
CycleM5a:
ret
;
; Measure time low, display time
;
CycleM6:
sbrc rFlg,bEdge
rjmp CycleM6a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'l'
rcall DisplMode
CycleM6a:
ret
;
; Measure time high and low, display pulse width ratio high in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active high time
;
CycleM7:
sbrs rFlg,bEdge
rjmp CycleM7a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rRes1,Z+ ; copy counter value
ld rRes2,Z+
ld rRes3,Z+
ld rRes4,Z+
add rDiv1,rRes1 ; add to total time
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
brcs CycleM7b
mov rmp,rRes1 ; copy high value to divisor
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM7b ; error
rcall DisplPw ; display the ratio
ldi ZL,'P'
rjmp DisplMode
CycleM7a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM7b: ; overflow
ldi rmp,'P'
rjmp PulseOvFlw
;
; Measure time high and low, display pulse width ratio low in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active low time
;
CycleM8:
sbrs rFlg,bEdge
rjmp CycleM8a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rmp,Z+ ; read high-time
ld R0,Z+
ld rDelL,Z+
ld rDelH,Z
add rDiv1,rmp ; add to total time
adc rDiv2,R0
adc rDiv3,rDelL
adc rDiv4,rDelH
mov rmp,rRes1 ; copy the active low time
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM8b ; error
rcall DisplPw ; display the ratio
ldi ZL,'p'
rjmp DisplMode
CycleM8a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM8b: ; overflow
ldi rmp,'p'
rjmp PulseOvFlw
;
; Converts an ADC value in R1:R0 to a voltage for display
; cAdc2U input: ADC value, output: Voltage in V for display
;
cAdc2U:
clr R2 ; clear the registers for left shift in R3:R2
clr R3
ldi rmp,HIGH(cMultiplier) ; Multiplier to R5:R4
mov R5,rmp
ldi rmp,LOW(cMultiplier)
mov R4,rmp
clr XL ; clear result in ZH:ZL:XH:XL
clr XH
clr ZL
clr ZH
cAdc2U1:
lsr R5 ; shift Multiplier right
ror R4
brcc cAdc2U2 ; bit is zero, don't add
add XL,R0 ; add to result
adc XH,R1
adc ZL,R2
adc ZH,R3
cAdc2U2:
mov rmp,R4 ; check zero
or rmp,R5
breq cAdc2U3 ; end of multiplication
lsl R0 ; multiply by 2
rol R1
rol R2
rol R3
rjmp cAdc2U1 ; go on multipying
cAdc2U3:
ldi rmp,$80 ; round up
add XL,rmp
ldi rmp,$00
adc XH,rmp
adc ZL,rmp
adc ZH,rmp
tst ZH ; check overflow
mov R1,XH ; copy result to R2:R1
mov R2,ZL
ldi XH,HIGH(sResult+16) ; point to result
ldi XL,LOW(sResult+16)
ldi rmp,'U'
st X+,rmp
breq cAdc2U5
ldi ZH,HIGH(2*AdcErrTxt)
ldi ZL,LOW(2*AdcErrTxt)
cAdc2U4:
lpm
tst R0
breq cAdc2U6
sbiw ZL,1
st X+,R0
rjmp cAdc2U4
cAdc2U5:
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DecConv
inc R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DecConv
ldi rmp,cDecSep
st X+,rmp
clr ZH
ldi ZL,100
rcall DecConv
ldi ZL,10
rcall DecConv
ldi rmp,'0'
add rmp,R1
st X+,rmp
ldi rmp,'V'
st X,rmp
lds rmp,sResult+17
cpi rmp,' '
brne cAdc2U6
ldi rmp,'='
sts sResult+17,rmp
cAdc2U6:
ret
;
AdcErrTxt:
.DB "overflw",$00
;
; ===========================================
; Lcd display routines
; ===========================================
;
.IF cDisplay ; if display connected
;
; LcdE pulses the E output for at least 1 us
;
LcdE:
sbi PORTB,bLcdE
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
.IF cFreq>2000000
nop
nop
.ENDIF
nop
nop
cbi PORTB,bLcdE
ret
;
; outputs the content of rmp (temporary
; 8-Bit-Interface during startup)
;
LcdRs8:
out PORTB,rmp
rcall LcdE
ret
;
; write rmp as 4-bit-command to the LCD
;
LcdRs4:
mov R0,rmp ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original back
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE
mov rmp,R0 ; restore rmp
ret
;
; write rmp as data over 4-bit-interface to the LCD
;
LcdData4:
push rmp ; save rmp
mov rmp,R0 ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original again
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE
rcall Delay40us
pop rmp ; restore rmp
ret
;
; writes the text in flash to the LCD, number of
; characters in rmp
;
LcdText:
lpm ; read character from flash
adiw ZL,1
rcall LcdData4 ; write to
rcall delay40us
dec rmp
brne LcdText
ret
;
; Inits the LCD with a 4-bit-interface
;
LcdInit:
ldi rmp,0x0F | (1<<bLcdE) | (1<<bLcdRs)
out DDRB,rmp
clr rmp
out PORTB,rmp
rcall delay15ms ; wait for complete self-init
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay4_1ms ; wait for 4.1 ms
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay100us ; wait for 100 us
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay40us ; delay 40 us
ldi rmp,0x02 ; Function set 4-bit-interface
rcall LcdRs8
rcall delay40us
.IF cDisplay2
ldi rmp,0x28 ; 4-bit-interface, two line display
.ELSE
ldi rmp,0x20 ; 4-bit-interface, single line display
.ENDIF
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x08 ; display off
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x01 ; display clear
rcall LcdRs4
rcall delay1_64ms ; delay 1.64 ms
ldi rmp,0x06 ; increment, don't shift
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x0C ; display on
rcall LcdRs4
rcall delay40us
ldi rmp,0x80 ; position on line 1
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
ldi ZH,HIGH(2*LcdInitTxt8)
ldi ZL,LOW(2*LcdInitTxt8)
.ELSE
ldi rmp,16
ldi ZH,HIGH(2*LcdInitTxt16)
ldi ZL,LOW(2*LcdInitTxt16)
.ENDIF
rcall LcdText
.IF cDisplay2
ldi rmp,0xC0 ; line 2
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
.ELSE
ldi XH,HIGH(sResult+25)
ldi XL,LOW(sResult+25)
ldi ZH,HIGH(2*LcdInitTxtMode)
ldi ZL,LOW(2*LcdInitTxtMode)
ldi rmp,6
LcdInitMode:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne LcdInitMode
ldi rmp,16
.ENDIF
rcall LcdText
.ENDIF
ret
.IF cDisplay8
LcdInitTxt8:
.DB "F-CNT V1"
.IF cDisplay2
.DB "-DG4FAC-"
.ENDIF
.ELSE
LcdInitTxt16:
.DB "Freq-counter V01"
.IF cDisplay2
.DB " (C)2005 DG4FAC "
LcdInitTxtMode:
.DB " Mode="
.ENDIF
.ENDIF
;
; Display frequency/time on Lcd
;
LcdDisplayFT:
.IF ! cDisplay2 ; single line display
cpi rMode,cModeVoltage ; voltage display selected?
breq LcdDisplayFT2
.ENDIF
ldi rmp,$80 ; set display position to line 1
rcall LcdRs4
rcall Delay40us
ldi ZH,HIGH(sResult) ; point Z to line buffer
ldi ZL,LOW(sResult)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayFT1:
ld R0,Z+ ; read a char
rcall LcdData4 ; display on LCD
dec rmp
brne LcdDisplayFT1
LcdDisplayFT2:
ret
;
; Display voltage on the display
;
LcdDisplayU:
.IF cDisplay2 ; two-line LCD connected
.IF !cDisplay8
lds rmp,sModeNext
subi rmp,-'0'
sts sResult+31,rmp
.ENDIF
ldi rmp,$C0 ; output to line 2
.ELSE
cpi rMode,cModeVoltage ; check switch
brne LcdDisplayU2
ldi rmp,$80 ; output to line 1
.ENDIF
rcall LcdRs4 ; set output position
rcall Delay40us
ldi ZH,HIGH(sResult+16) ; point to result
ldi ZL,LOW(sResult+16)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayU1:
ld R0,Z+ ; read character
rcall LcdData4
dec rmp ; next char
brne LcdDisplayU1 ; continue with chars
LcdDisplayU2:
ret
;
.ENDIF ; end LCD routines to be included
;
; ===========================================
; Uart routines
; ===========================================
;
.IF cUart
UartInit: ; Init the Uart on startup
.EQU cUbrr = (cFreq/cBaud/16)-1 ; calculating UBRR single speed
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi rmp,HIGH(cUbrr) ; set URSEL to zero, set baudrate msb
out UBRRH,rmp
ldi rmp,LOW(cUbrr) ; set baudrate lsb
out UBRRL,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; set 8 bit characters
out UCSRC,rmp
ldi rmp,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable RX/TX and RX-Ints
out UCSRB,rmp
rcall delay10ms ; delay for 10 ms duration
ldi ZH,HIGH(2*txtUartInit)
ldi ZL,LOW(2*txtUartInit)
rjmp UartSendTxt
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
; .EQU UartRxbLen = 38 ; Buffer length in bytes
; sUartFlag: ; flag register for Uart
; .BYTE 1
; .EQU bUMonU = 0 ; displays voltage over Uart
; .EQU bUMonF = 1 ; displays frequency over Uart
; ; free: bits 2..7
; sUartMonUCnt: ; counter for Monitoring voltage
; .BYTE 1
; sUartMonURpt: ; counter preset for monitoring voltage
; .BYTE 1
; sUartRxBp: ; buffer pointer
; .BYTE 1
; sUartRxBs: ; buffer
; .BYTE UartRxbLen
; sUartRxBe: ; buffer end
; .EQU cNul = $00
; .EQU cClrScr = $0C
; .EQU cCr = $0D
; .EQU cLf = $0A
;
UartRxLine:
cbr rFlg,1<<bUartRxLine ; clear line complete flag
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi ZH,HIGH(UartReturn) ; push return adress to stack
ldi ZL,LOW(UartReturn)
push ZL
push ZH
ldi ZH,HIGH(sUartRxBs) ; set Z to Buffer-Start
ldi ZL,LOW(sUartRxBs)
ld rmp,Z+ ; read first character
cpi rmp,'h' ; help?
brne UartRxLine1
rjmp UartHelp
UartRxLine1:
cpi rmp,'?' ; help?
brne UartRxLine2
rjmp UartHelp
UartRxLine2:
cpi rmp,'U' ; monitor U on
brne UartRxLine3
rcall UartGetPar
sec
rjmp UartMonUSetC
UartRxLine3:
cpi rmp,'u' ; monitor U off
brne UartRxLine4
clc
rjmp UartMonUSetC
UartRxLine4:
cpi rmp,'F' ; monitor F on
brne UartRxLine5
rcall UartGetPar
sec
rjmp UartMonFSetC
UartRxLine5:
cpi rmp,'f' ; monitor f off
brne UartRxLine6
clc
rjmp UartMonFSetC
UartRxLine6:
cpi rmp,'p' ; parameter?
brne UartRxLine7
rjmp UartMonPar
UartRxLine7:
ldi ZH,HIGH(2*txtUartUnknown) ; send unknown command
ldi ZL,LOW(2*txtUartUnknown)
ret
UartHelp:
ldi ZH,HIGH(2*txtUartHelp) ; send help text
ldi ZL,LOW(2*txtUartHelp)
ret
UartMonUSetC:
lds rmp,sUartFlag
brcs UartMonUSetC1
cbr rmp,1<<bUMonU ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOff)
ldi ZL,LOW(2*txtUartUOff)
ret
UartMonUSetC1:
brne UartMonUSetC2
sts sUartMonURpt,R0
sts sUartMonUCnt,R0
UartMonUSetC2:
sbr rmp,1<<bUMonU ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOn)
ldi ZL,LOW(2*txtUartUOn)
ret
UartMonFSetC:
lds rmp,sUartFlag
brcs UartMonFSetC1
cbr rmp,1<<bUMonF ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOff)
ldi ZL,LOW(2*txtUartFOff)
ret
UartMonFSetC1:
brne UartMonFSetC2
sts sUartMonFRpt,R0
sts sUartMonFCnt,R0
UartMonFSetC2:
sbr rmp,1<<bUMonF ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOn)
ldi ZL,LOW(2*txtUartFOn)
ret
UartMonPar:
ldi ZH,HIGH(2*txtUartNul)
ldi ZL,LOW(2*txtUartNul);
ldi rmp,'U'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonURpt
rcall UartHexR
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'F'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonFRpt
rjmp UartHexR
;
; Get Parameter from line
;
UartGetPar:
clr R0 ; result register
ld rmp,Z+ ; read char
cpi rmp,cCr ; carriage return
breq UartGetParNoPar
cpi rmp,cLf ; line feed
breq UartGetParNoPar
cpi rmp,'=' ;
brne UartGetParErr
UartGetPar1:
ld rmp,Z+ ; read next char
cpi rmp,cCr ; carriage return?
breq UartGetPar2
cpi rmp,cLf ; line feed?
breq UartGetPar2
subi rmp,'0' ; subtract 0
brcs UartGetParErr
cpi rmp,10 ; larger than 9?
brcc UartGetParErr
mov rir,R0 ; copy to rir
lsl R0 ; * 2
brcs UartGetParErr
lsl R0 ; * 4
brcs UartGetParErr
add R0,rir ; * 5
brcs UartGetParErr
lsl R0 ; * 10
brcs UartGetParErr
add R0,rmp ; add new decimal
brcs UartGetParErr
rjmp UartGetPar1
UartGetPar2:
sez
ret
UartGetParErr:
ldi ZH,HIGH(2*txtUartErr)
ldi ZL,LOW(2*txtUartErr)
rcall UartSendTxt
UartGetParNoPar:
clz ; No parameter set
ret
;
; Hex output over Uart, for debugging
;
UartHexR:
push rmp
swap rmp
rcall UartHexN
pop rmp
UartHexN:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs UartHexN1
subi rmp,-7
UartHexN1:
rjmp UartSendChar
ret
;
; Return from Uart-Routines, displays text in Z
;
UartReturn:
rcall UartSendTxt ; send text in Z
ldi ZH,HIGH(2*txtUartCursor)
ldi ZL,LOW(2*txtUartCursor)
rjmp UartSendTxt
;
; Send character in rmp over Uart
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartSendChar
out UDR,rmp
ret
;
; Monitoring the voltage over the Uart
;
UartMonU:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonU ; displays voltage over Uart
ret
lds rmp,sUartMonUCnt ; read counter
dec rmp
sts sUartMonUCnt,rmp
brne UartMonU2
lds rmp,sUartMonURpt
sts sUartMonUCnt,rmp
ldi ZH,HIGH(sResult+16)
ldi ZL,LOW(sResult+16)
ldi rmp,8
UartMonU1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonU1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonU1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonU2:
ret
;
; Monitor frequency over UART
;
UartMonF:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonF ; displays frequency over Uart
ret
lds rmp,sUartMonFCnt ; read counter
dec rmp
sts sUartMonFCnt,rmp
brne UartMonF2
lds rmp,sUartMonFRpt
sts sUartMonFCnt,rmp
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,16
UartMonF1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonF1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonF1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonF2:
ret
;
; Send text from flash to UART, null byte ends transmit
;
UartSendTxt:
lpm ; read character from flash
adiw ZL,1
tst R0 ; check end of text
breq UartSendTxtRet
UartSendTxtWait:
sbis UCSRA,UDRE ; wait for empty char
rjmp UartSendTxtWait
out UDR,R0 ; send char
rjmp UartSendTxt
UartSendTxtRet:
ret
;
; Uart text constants
;
txtUartInit:
.DB " ",cClrScr
.DB "************************************************* ",cCr,cLf
.DB "* Frequency- and voltmeter (C)2005 by g.schmidt * ",cCr,cLf
.DB "************************************************* ",cCr,cLf
txtUartMenue:
.DB cCr,cLf,"Commands: <h>elp",cCr,cLf
txtUartCursor:
.DB cCr,cLf,"i> ",cNul

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm (3 of 4)1/20/2009 7:40:33 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm

txtUartUnknown:
.DB cCr,cLf,"Unknown command!",cNul,cNul
txtUartUOff:
.DB "Voltage monitoring is off.",cNul,cNul
txtUartUOn:
.DB "Voltage monitoring is on. ",cNul,cNul
txtUartFOff:
.DB "Frequency monitoring is off.",cNul,cNul
txtUartFOn:
.DB "Frequency monitoring is on. ",cNul,cNul
txtUartErr:
.DB "Error in parameter! ",cNul,cNul
txtUartHelp:
.DB cCr,cLf,"Help: ",cCr,cLf
.DB "U[=N](on) or u(Off): monitor voltage output, N=1..255,",cCr,cLf
.DB "F[=N](On) or f(Off): monitor frequency output N=1..255, ",cCr,cLf
.DB "p: display monitoring parameters, ",cCr,cLf
.DB "h or ?: this text."
txtUartNul:
.DB cNul,cNul
.ENDIF
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV03.asm (4 of 4)1/20/2009 7:40:33 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/LiesMich3.txt

****************************************************
* Anleitung fuer Frequenzzaehler v0.3 vom 9.1.2009 *
****************************************************

Abschnitte:
-----------
1. Einstellungen vor dem Assemblieren
2. Bei der Programmierung zu beachten
3. Messmodus
3.1 Messmodi
3.2 Anzeige des Messmodus
4. Darstellung auf dem Display
4.1 Darstellung bei zweizeiligen LCD-Displays
4.2 Darstellung bei einzeiligen LCD-Displays
4.3 Darstellung bei 16-/20-Zeichen-Displays
4.4 Darstellung bei 8 Zeichen-Displays
5. Darstellung auf der seriellen Schnittstelle
5.1 Befehle der seriellen Schnittstelle
5.2 Format von Spannungs- und Messausgaben

1. Einstellungen vor dem Assemblieren


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

Die folgenden Einstellungen sind vor dem Assemblieren


in der Datei fcountV03.asm zu kontrollieren und ggfs.
zu aendern:

- Die Schalter debug und debugpulse muessen auf 0


stehen.

- Wenn ein LCD-Display angeschlossen ist, muss


cDisplay auf 1 stehen, sonst auf 0.

- Wenn das angeschlossene LCD-Display 8 Zeichen pro


Zeile darstellen kann, muss cDisplay8 auf 1 stehen.
Wenn es 16 oder 20 Zeichen pro Zeile darstellen
kann, muss cDisplay8 auf 0 stehen.

- Wenn das angeschlossene LCD-Display eine einzige


Zeile darstellen kann, muss cDisplay2 auf 0 stehen.
Wenn es zwei oder mehr Zeilen darstellen kann, muss
cDisplay2 auf 1 stehen.

- Wenn die serielle Schnittstelle angeschlossen ist


und bedient werden soll, muss cUart auf 1 stehen.
Ist keine serielle Schnittstelle angeschlossen oder
soll sie nicht verwendet werden, wird cUart auf
0 gesetzt.

- Ist der Vorteiler durch 8 an einem anderen Portbit


als PC5 angeschlossen, sind die Ports pPresc und
pPrescD sowie das Portbit bPresc entsprechend zu
aendern.

- Wird der Prozessortakt mit einer anderen Frequenz


als 16 MHz betrieben, ist diese in cFreq anzugeben.

- Soll die serielle Schnittstelle mit einer anderen


Baudrate als 9600 arbeiten, ist cBaud entsprechend
zu aendern.

- Ist der Vorteiler fuer die Spannungsmessung mit


zwei anderen Widerstaenden bestueckt als mit 1M,
sind die beiden Werte cR1 und cR2 entsprechend zu
aendern. Wenn die angezeigte Spannung wesentlich
von der Eingangsspannung abweicht, ist cRin zu
aendern: kleinere Werte fuer cRin ergeben eine
hoehere angezeigte Spannung, groeszere eine
niedrigere angezeigte Spannung.

2. Bei der Programmierung des ATmega8 zu beachten


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

- Die Fuses "Ext.Crystal/Resonator HighFreq.; Start-up


time: 16K CK + 64 ms "CKSEL=1111 SUT=11]" und CKOPT
muessen gesetzt werden, alle anderen internen und
externen clock fuses muessen geloescht werden. Die
Screenshots zeigen die Fuses (FusesPony.gif bzw.
FusesStudio1.gif und FusesStudio2.gif).

3. Messmodus
------------

3.1 Messmodi

Der Messmodus wird mit dem Potentiometer ausge-


waehlt. Die folgenden Messmodi sind einstellbar:
0: Frequenzmessung mit Vorteiler, Gatezeit 0,25 s,
Ergebnis in Hz
1: Frequenzmessung ohne Vorteiler, Gatezeit 0,25 s,
Ergebnis in Hz
2: Frequenzmessung als Periodenmessung mit Frequenz-
umrechnung, Ergebnis in 0,01 Hz bzw. 0,001 Hz
3: Umdrehungsmessung, ohne Vorteiler, ueber
Periodenmessung mit Umrechnung, Ergebnis in Upm
4: Periodendauer gesamte Schwingung, Ergebnis in
Mikrosekunden
5: Periodendauer High-Periode, Ergebnis in Mikro-
sekunden
6: Periodendauer Low-Periode, Ergebnis in Mikro-
sekunden
7: Periodenanteil High-Periode, Ergebnis in 0,1%
8: Periodenanteil Low-Periode, Ergebnis in 0,1%
9: Spannungsmessung, Ergebnis in 0,001 Volt
Die Auswahl von Modus 9 (rechter Poti-Anschlag)
schaltet die Frequenz-/Zeit-/Periodenmessungen aus.

3.2 Darstellung des Messmodus

Der Messmodus wird am Anfang der LCD-Zeile mit


einem Buchstaben und dem Gleichheitszeichen ange-
zeigt (Format "X="). Bei 8-Zeichen-LCDs wird das
Gleichheitszeichen bzw. die Messmoduskennung nur
dann angezeigt, wenn der anzuzeigende Messwert
genuegend klein ist.

Bei der Anzeige von Messwerten werden folgende Ab-


kuerzungen fuer den Messmodus verwendet:
- "F=": Frequenz in Hz, gemessen mit Vorteiler, Auf-
loesung +/- 32 Hz
- "f=": Frequenz in Hz, gemessen ohne Vorteiler, Auf-
loesung +/- 4 Hz
- "v=": Frequenz in Hz mit Dezimalstellen, gemessen
ueber eine Zeitmessung, Aufloesung +/- 0,01 Hz
- "u=": Umdrehungszahl in Upm, gemessen ueber eine
Zeitmessung, Aufloesung +/- 1 Upm
- "t=": Schwingungsdauer in Mikrosekunden, Aufloesung
+/- 1 Mikrosekunde
- "h=": Dauer einer 1-Periode am Eingang, Aufloesung
+/- 1 Mikrosekunde
- "l=": Dauer einer 0-Periode am Eingang, Aufloesung
+/- 1 Mikrosekunde
- "P=": Periodenanteil einer 1-Periode am Eingang in
%, Aufloesung +/- 0,1%
- "p=": Periodenanteil einer 0-Periode am Eingang in
%, Aufloesung +/- 0,1%
- "U=": Spannung in Volt am Spannungseingang, Aufloe-
sung abhaengig vom Spannungsteiler am Eingang, bei
1M+1M ca. 4 Millivolt.

4. Darstellung auf dem Display


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

Die Aktualisierung des Dislays erfolgt vier mal pro


Sekunde bzw. bei laengeren Schwingungsdauern nach dem
Ablauf der Messperiode.

4.1 Darstellung bei zweizeiligen LCD-Displays

Die erste Zeile stellt je nach eingestelltem Messmodus


die Frequenz, die Zeit oder den Periodenanteil dar. Die
zweite Zeile stellt die Spannung dar.
Bei zweizeiligen LCDs mit mehr als 8 Zeichen pro Zeile
wird der Messmodus (0..9) am Ende der zweiten Zeile
dargestellt.

4.2 Darstellung bei einzeiligen LCD-Displays

Das Display stellt die Ergebnisse der Frequenz-, Zeit-


und Periodenanteil-Messung in den Modi 0 .. 8 dar.
Bei Modus 9 (rechter Poti-Anschlag) wird die Spannung
angezeigt.

4.3 Darstellung bei 16-/20-Zeichen-Displays

Die Anzeige erfolgt vollstaendig mit Moduskennung,


Tausender- und Dezimaltrennzeichen sowie mit Dimension.
Mode Format
-----------------------
0 "F=99.999.999 Hz "
1 "f= 9.999.999 Hz "
2 "v= 9.999,999 Hz "
3 "u= 9.999.999 rpm"
4 "t=99.999.999 us "
5 "h=99.999.999 us "
6 "l=99.999.999.us "
7 "P=100,0% "
8 "p=100,0% "
9 "U=9,999V "

4.4 Darstellung bei 8 Zeichen-Displays

Periodenanteile und die Spannung werden vollstaendig


angezeigt.
Die Darstellung der anderen Messgroeszen erfolgt
verkuerzt. Unterdrueckt werden:
- die Ausgabe von Tausender-Trennzeichen,
- die Ausgabe der Dimension,
- erforderlichenfalls das Gleichheitszeichen und der
Buchstabe der Moduskennung.
Die Ausgabe erfolgt bei
- Frequenzen in Hz
- Umdrehungen in Upm
- Zeiten in Mikrosekunden.

Mode Format kurz Format lang


----------------------------
0 "F=999999" "99999999"
1 "f=999999" "99999999"
2 "v=999999" "99999999"
3 "u=999999" "99999999"
4 "t=999999" "99999999"
5 "h=999999" "99999999"
6 "l=999999" "99999999"
7 "P=100,0%" "P=100,0%"
8 "p=100,0%" "p=100,0%"
9 "U=9,999V" "U=9,999V"

5. Darstellung auf der seriellen Schnittstelle


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

Die serielle Schnittstelle sendet beim Prozessorstart


den folgenden Text ueber die Schnittstelle:

*************************************************
* Frequency- and voltmeter (C)2005 by g.schmidt *
*************************************************

Commands: <h>elp

i>

5.1 Befehle der seriellen Schnittstelle

Folgende Kommandos sind implementiert:

u : Spannungsausgabe ausschalten
U : Spannungsausgabe einschalten
U=123 : Intervall fuer Spannungsausgabe 123 Zyklen
f : Frequenzausgabe ausschalten
F : Frequenzausgabe einschalten
F=123 : Intervall fuer Frequenzausgabe 123 Zyklen
p : Zeige eingestellte Intervalle an
h, ? : Hilfe-Ausgabe

5.2 Format von Spannungs- und Messausgaben

Die Ausgabe von Spannungen erfolgt im Format


"U=4,958V<CR><LF>"
Die Ausgabe von Frequenzen ist vom eingestellten Modus
abhaengig, also z. B. in Modus 0
"F=1.234.567 Hz<CR><LF>"

http://www.avr-asm-tutorial.net/avr_de/fcount/LiesMich3.txt1/20/2009 7:40:44 PM
Geschenkprojekt AVR-Eieruhr - Assembler-Quellcode

Pfad: Home => AVR-Übersicht => Anwendungen => Eieruhr => Assembler-Quellcode

Die ATtiny2313V-Eieruhr - Assembler-Quellcode

; *****************************************************
; * ATtiny2313-Eieruhr, Version 1, 20.10.2006 *
; * (C)2006 by G.Schmidt info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "tn2313def.inc"
.LIST
;
; ***************************************
; Fuses-Voreinstellungen im ATtiny2313V
; ***************************************
;
; - Internen RC-Oszillator auf 4 MHz, CLKSEL3:0 = 0010, SUT1:0 =
10
; - Interner Clockteiler auf 8, CKDIV8 = Enabled
;
; ***************************************
; Hardware - Schaltung
; ***************************************
;
; __________
; / |_| |
; +3V O--|Res VCC|--O +3V
; | |
; L1K O--|PD0 PB7|--O L10A
; | |
;L1A/L2K O--|PD1 PB6|--O L9A/L10K
; | AT |
; O--|PA1 PB5|--O L8A/L9K
; | tiny |
; O--|PA0 PB4|--O L7A/L8K
; | 2313 |
;L2A/L3K O--|PD2 PB3|--O
; | V |
;L4K/L3A O--|PD3 PB2|--||--O Lsp
; | (OC0A)|
;L5K/L4A O--|PD4 PB1|--O
; | |
;L6K/L5A O--|PD5 PB0|--O L0K
; | |
; GND O--|GND PD6|--O L6A/L7K
; |___________|
;
;
; ***************************************
; Definiere Ports und Portbits
; ***************************************
;
.EQU pOcO = PORTB
.EQU dOcO = DDRB
.EQU bOcO = 2
;
.EQU pL0K = PORTB
.EQU dL0K = DDRB
.EQU bL0K = 0
;
.EQU pL1K = PORTD
.EQU dL1K = DDRD
.EQU bL1K = 0
;
.EQU pL1A = PORTD
.EQU dL1A = DDRD
.EQU bL1A = 1
;
.EQU pL2K = PORTD
.EQU dL2K = DDRD
.EQU bL2K = 1
;
.EQU pL2A = PORTD
.EQU dL2A = DDRD
.EQU bL2A = 2
;
.EQU pL3K = PORTD
.EQU dL3K = DDRD
.EQU bL3K = 2
;
.EQU pL3A = PORTD
.EQU dL3A = DDRD
.EQU bL3A = 3
;
.EQU pL4K = PORTD
.EQU dL4K = DDRD
.EQU bL4K = 3
;
.EQU pL4A = PORTD
.EQU dL4A = DDRD
.EQU bL4A = 4
;
.EQU pL5K = PORTD
.EQU dL5K = DDRD
.EQU bL5K = 4
;
.EQU pL5A = PORTD
.EQU dL5A = DDRD
.EQU bL5A = 5
;
.EQU pL6K = PORTD
.EQU dL6K = DDRD
.EQU bL6K = 5
;
.EQU pL6A = PORTD
.EQU dL6A = DDRD
.EQU bL6A = 6
;
.EQU pL7K = PORTD
.EQU dL7K = DDRD
.EQU bL7K = 6
;
.EQU pL7A = PORTB
.EQU dL7A = DDRB
.EQU bL7A = 4
;
.EQU pL8K = PORTB
.EQU dL8K = DDRB
.EQU bL8K = 4
;
.EQU pL8A = PORTB
.EQU dL8A = DDRB
.EQU bL8A = 5
;
.EQU pL9K = PORTB
.EQU dL9K = DDRB
.EQU bL9K = 5
;
.EQU pL9A = PORTB
.EQU dL9A = DDRB
.EQU bL9A = 6
;
.EQU pL10K = PORTB
.EQU dL10K = DDRB
.EQU bL10K = 6
;
.EQU pL10A = PORTB
.EQU dL10A = DDRB
.EQU bL10A = 7
;
; ***************************************
; Funktionsweise Timing
; ***************************************
;
; Timer1 = Zeitmessung
; _______ ______ ______ ______ _____ ______
; |RC-Osc.| | CDiv |500|Presc.|62,5|TC1CNT|5Hz| LED |0,5|MinCnt|
; | 4 MHz |===<| / 8 |==>| / 8 |===>|/12500|==>|Count|==>| / 30 |
==>1 Min.
; |_______| |______|kHz|______|kHz |______| |_____|Hz |______|
; |
; Timer0 = NF-Erzeugung|
; | ______ ______
; | |Presc.| |TC0CNT|992Hz
; |=>| / 8 |==>| / 63 |===> OC0A = Beep-
Lautsprecher
; |______| |______|
;
;
; ***************************************
; Register
; ***************************************
;
.DEF rmp = R16
.DEF rFlg = R17
.DEF rLed = R18
.DEF rSec = R19
.DEF rMin = R20
.DEF rNb = R21
;
; ***************************************
; Reset und Interrupt-Vektoren
; ***************************************
;
.CSEG
.ORG $0000
rjmp Main ; Reset
reti ; INT0 Interrupt
reti ; INT1 Interrupt
reti ; TC1Capt Interrupt
rjmp TC1CmpA ; Timer 1 Compare A match
reti ; TC1 Overflow Int
reti ; TC0 Overflow Int
reti ; UART0 RX Int
reti ; UART0 TX Int
reti ; Ana Comp Int
reti ; PCINT
reti ; TC1 CompB Int
reti ; TC0 Compare Match A Int
reti ; TC0 Compare Match B Int
reti ; USISTART Int
reti ; USIOverflow Int
reti ; EERDY Int
reti ; WDT Overflow Int
;
; ***************************************
; TC1 Compare Match A Interrupt Routine
; ***************************************
;
TC1CmpA:
set
reti
;
; ***************************************
; Hauptprogramm
; ***************************************
;
Main:
; Stack init
ldi rmp,LOW(RAMEND) ; Setze Stackpointer
out SPL,rmp
; Init Register
ldi rFlg,0 ; Init Flagge
ldi rLed,0 ; Init LEDs
ldi rSec,0 ; Init Sekundenzaehler
ldi rMin,1 ; Init Minutenzaehler
ldi rNb,1 ; Init Beep-Zaehler
; Init OCR0A-Output fuer Beep
sbi dOcO,bOcO
; Init Timer 1 fuer Zeit- und Lampensteuerung
ldi rmp,HIGH(12500) ; CTC-Wert
out OCR1AH,rmp
ldi rmp,LOW(12500)
out OCR1AL,rmp
clr rmp ; Kontrollwort A
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; auf CTC
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; Timer1-Interrupt
out TIMSK,rmp
; Init Timer 0 fuer Beep-Ausgang
ldi rmp,(1<<COM0A0)|(1<<WGM01) ; CTC, Toggle Compare A
out TCCR0A,rmp
ldi rmp,1<<CS01 ; beep an
out TCCR0B,rmp
ldi rmp,63 ; CTC-Wert
out OCR0A,rmp
ldi rmp,1<<SE ; sleep idle
out MCUCR,rmp
sei ; Enable Ints
;
; ***************************************
; Hauptprogramm - Loop
; ***************************************
;
; in Schlafmodus gehen
An:
sleep ; Schlafen
nop ; Aufwachen
brtc An ; T-Flag von Timer nicht gesetzt
clt ; T-Flag zuruecksetzen
sbrc rLed,0 ; Bit 0 ist Beep-Steuerung
rjmp BeepAus
tst rNb ; teste beeps = 0
breq BeepAus ; schalte Beep aus
ldi rmp,1<<CS01 ; beep an
out TCCR0B,rmp
dec rNb ; verringere Beeps
rjmp LedAus
BeepAus:
ldi rmp,0 ; Beep ausschalten, Timer stoppen
out TCCR0B,rmp
LedAus:
ldi ZH,HIGH(TabAus) ; LED ausschalten
ldi ZL,LOW(TabAus)
add ZL,rLed ; aktuelle LED addieren
brcc MachAus
inc ZH
MachAus:
ijmp ; aktuelle LED deaktivieren
Aus: ; LED ist ausgeschaltet
inc rLed ; erhoehe Zaehler
cpi rLed,10 ; schon bei Zehn?
brne Weiter ; nein
clr rLed ; ja, von vorne beginnen
inc rSec ; 0,5-Sekundenzaehler erhoehen
cpi rSec,30 ; schon bei 30?
brcs Weiter ; nein, noch nicht
clr rSec ; ja, loesche 0,5-Sekundenzaehler
mov rNb,rMin ; Minuten in Beep-Zaehler kopieren
inc rMin ; Minutenzaehler erhoehen
cpi rMin,11 ; 10 Minuten abgelaufen?
brcs Weiter ; nein
clr rMin ; Mintenzaehler von vorne
ldi rNb,255 ; Beep fuer ganze Minute an
sbi dL0K,bL0K ; Ausgang gelbe Lampe an
cbi pL0K,bL0K ; gelbe Lampe an
Weiter: ; aktuelle LED rot oder gruen?
ldi ZH,HIGH(TabRot) ; versuche es mit rot
ldi ZL,LOW(TabRot)
cp rLed,rMin ; aktuelle LED kleiner als Minutenzaehler
brcs Weiter1 ; nein
ldi ZH,HIGH(TabGruen) ; nein, es ist gruen
ldi ZL,LOW(TabGruen)
Weiter1: ; Lampe anschalten
add ZL,rLed ; mache die richtige LED an
brcc MachAn
inc ZH
MachAn: ; schalte Lampe an
ijmp
;
; ***************************************
; Sprungtabellen
; ***************************************
;
; Sprungtabelle der Lampen-Routinen fuer Rot
TabRot:
rjmp L1R
rjmp L2R
rjmp L3R
rjmp L4R
rjmp L5R
rjmp L6R
rjmp L7R
rjmp L8R
rjmp L9R
rjmp L10R
; Sprungtabelle der Lampen-Routinen fuer Gruen
TabGruen:
rjmp L1G
rjmp L2G
rjmp L3G
rjmp L4G
rjmp L5G
rjmp L6G
rjmp L7G
rjmp L8G
rjmp L9G
rjmp L10G
; Sprungtabelle der Lampen-Routinen fuer Ausschalten
TabAus:
rjmp L1A
rjmp L2A
rjmp L3A
rjmp L4A
rjmp L5A
rjmp L6A
rjmp L7A
rjmp L8A
rjmp L9A
rjmp L10A
;
; ***************************************
; Lampen - Schaltroutinen
; ***************************************
;
; Lampen ausschalten
L1A:
cbi pL1A,bL1A
cbi pL1K,bL1K
cbi dL1A,bL1A
cbi dL1K,bL1K
rjmp Aus
L2A:
cbi pL2A,bL2A
cbi pL2K,bL2K
cbi dL2A,bL2A
cbi dL2K,bL2K
rjmp Aus
L3A:
cbi pL3A,bL3A
cbi pL3K,bL3K
cbi dL3A,bL3A
cbi dL3K,bL3K
rjmp Aus
L4A:
cbi pL4A,bL4A
cbi pL4K,bL4K
cbi dL4A,bL4A
cbi dL4K,bL4K
rjmp Aus
L5A:
cbi pL5A,bL5A
cbi pL5K,bL5K
cbi dL5A,bL5A
cbi dL5K,bL5K
rjmp Aus
L6A:
cbi pL6A,bL6A
cbi pL6K,bL6K
cbi dL6A,bL6A
cbi dL6K,bL6K
rjmp Aus
L7A:
cbi pL7A,bL7A
cbi pL7K,bL7K
cbi dL7A,bL7A
cbi dL7K,bL7K
rjmp Aus
L8A:
cbi pL8A,bL8A
cbi pL8K,bL8K
cbi dL8A,bL8A
cbi dL8K,bL8K
rjmp Aus
L9A:
cbi pL9A,bL9A
cbi pL9K,bL9K
cbi dL9A,bL9A
cbi dL9K,bL9K
rjmp Aus
L10A:
cbi pL10A,bL10A
cbi pL10K,bL10K
cbi dL10A,bL10A
cbi dL10K,bL10K
rjmp Aus
; Lampe auf Gruen
L1G:
sbi pL1A,bL1A
cbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2G:
sbi pL2A,bL2A
cbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3G:
sbi pL3A,bL3A
cbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4G:
sbi pL4A,bL4A
cbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5G:
sbi pL5A,bL5A
cbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6G:
sbi pL6A,bL6A
cbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7G:
sbi pL7A,bL7A
cbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8G:
sbi pL8A,bL8A
cbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9G:
sbi pL9A,bL9A
cbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10G:
sbi pL10A,bL10A
cbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
; Lampe auf Rot
L1R:
cbi pL1A,bL1A
sbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2R:
cbi pL2A,bL2A
sbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3R:
cbi pL3A,bL3A
sbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4R:
cbi pL4A,bL4A
sbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5R:
cbi pL5A,bL5A
sbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6R:
cbi pL6A,bL6A
sbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7R:
cbi pL7A,bL7A
sbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8R:
cbi pL8A,bL8A
sbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9R:
cbi pL9A,bL9A
sbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10R:
cbi pL10A,bL10A
sbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
;
; Ende des Quellcodes
;

An den Seitenanfang

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr_asm.html1/20/2009 7:40:49 PM
Geschenkprojekt AVR-Eieruhr

Pfad: Home => AVR-Übersicht => Anwendungen => Eieruhr

Als kleines Bastelprojekt - Zum Spaß machen - Fingerübung in Assembler

Die ATtiny2313V-Eieruhr
1. Beschreibung
2. Aufbau
3. Funktionsweise

1. Beschreibung
Wer kennt das nicht: der oder die X.Y. hat bald Geburtstag, man ist geladen, und X.Y. hat schon alles. Jetzt
kann man phantasielos in irgendein Geschenkgeschäft gehen, irgendetwas völlig Überflüssiges kaufen,
einpacken lassen und nur noch hoffen, dass nicht vier bis fünf der anderen Geladenen dasselbe Geschäft
aufgesucht, den gleichen schlechten Geschmack haben wie man selbst und mit demselben Ramsch antraben
("Bestimmt kann man die vier anderen umtauschen!" Gegen was bloß?).

Wer löten kann, ist jetzt klar im Vorteil: ab sofort gibt es selbstgemachte Bastelware auf den Gabentisch.
Das Bibbern ist jetzt vorbei, denn unsere Verwandten und Bekannten kriegen jetzt nach und nach alle einen
schicken, individuellen und geschmackssicher gestalteten Eierwecker. Natürlich bestückt mit einem
hochmodernen Schicki-Micki-Mikroprofessor, schließlich sind wir eine technologisch führende Nation, auf
unseren Erfindungsreichtum stolz, und arbeiten nicht mehr mit diesem säuregereinigten Quarzsand in einem
Glaskolben mit Verengung. Den kann keiner so schnell kopieren, das bleibt ein individuelles Geschenk.
Rieselsand war vorgestern, heute ist Piepsen und Blinken.

Das Prinzip ist einfach erklärt: eine Reihe von LEDs leuchtet wie bei einer Bandanzeige grün und rot auf,
immer wenn eine Minute um ist, wird eine weitere LED des Bands rot, eine weniger grün. Damit die Kiste
aus einer Batterie betrieben werden kann und nicht nach ein Mal Eierkochen die Batterie alle ist, leuchtet
immer nur eine LED gleichzeitig. Das Band läuft aber schnell durch, damit auch was los ist in der Kiste und
der Rotstand mit kurzem Blick erfasst werden kann.

Damit der geneigte Leser einer Tageszeitung beim Eierkochen nicht die Augen gebannt auf den Eierkocher
richten muss, gibt die Eieruhr bei jeder vollen Minute die Anzahl der Kochminuten auch durch vorgezählte
Piepser aus. Ist also im Gegensatz zur Sandvariante auch für sehbehinderte Zeitgenossen geeignet. Sind die
10 Minuten voll, zeigt eine gelbe LED und ein ganz langes Piepsen an, dass der Dotter jetzt grün ist und das
Ei getrost weggeworfen werden kann.

Hier wird jetzt nur die Elektronik beschrieben, den Einbau in ein Gehäuse müssen Sie ganz von selbst
kreativ lösen. Für die Anordnung der LEDs gilt:

1. Ein gerades Band ist mit seiner strengen Geometrie für geradlinige Zeitgenossen besser geeignet (z.
B. Mathematiker, Hausmeister), Modell "straight forward",
2. Kreis geht aber auch, ist eher für körperlich rundlich gebaute Beschenkte angebracht, Modell
"Bierbauch".
3. Für den verspielten Charakter ist am passendsten die eierförmige Anordnung, auch für den
Vergesslichen ist das am schönsten (erinnert unmittelbar an die vorgesehene Verwendung der
Schachtel), Modell "forget it".
4. Für den eher chaotischen, die Unordnung genießenden und die Komplexität liebenden Bekannten
ordnen sie alle LEDs wahllos verteilt und durcheinander auf einer völlig unregelmässigen
Grundfläche an, Modell "Hundertwasser".
5. Für den Spielsüchtigen: Vielleicht vertauschen sie auch noch mit jeder Minute ein wenig die
Reihenfolge der LEDs per Software. Er wird es lieben, zu raten, wo das nächste Lämpchen rot
werden wird, Modell "vote&surprise".

Aus eigener Erfahrung hat es sich sehr bewährt, den Beschenkten auch noch mit einer individuell
gestalteten Bedienungsanleitung auszustatten. Witzige Formulierungen, wie z.B. deutsche Wörter mit
taiwanesischer Grammatik, bringen Lacherfolge. Oder schreiben Sie die Anleitung in Englisch, füttern sie
in den Babelfish mit der Anweisung, sie in Niederländisch oder Flämisch zu übersetzen und ersetzen alle
Hauptwörter und einen zufällig ausgewählten Anteil der anderen Wörter wieder durch den deutschen
Begriff. Als Vorlage hier was im RTF-Format oder als Open-Office-Format.

An den Seitenanfang

Aufbau
D

Schaltbild ist recht einfach: die beiden Batterien (2*AA, 2*AAA geht aber auch) speisen das Ganze mit
3 V, mehr Spannung (z.B. 5 V) tötet die LEDs sehr schnell. Die Reihe der Duo-LEDs rot/grün ist mit
Strombrems-Widerständen als Kaskade aufgebaut, jede der LEDs lässt sich von den beiden
angeschlossenen Portpins aus entweder links rum oder rechts rum mit Strom versorgen und ändert so ihre
Farbe. Beim Einbau der LEDs kommt es nur darauf an, alle LEDs in gleicher Farbrichtung einzubauen, die
Farbe kann in der Software leicht vertauscht werden.

Alle nicht angesteuerten Portpins sind per Software auf inaktiven Tristate gesetzt und stören daher nicht.
Der ATtiny2313V (ohne V geht auch) treibt immer nur eine LED, der Spannungsabfall an den Ausgängen
unter Last ist bei der Bemessung der Widerstände berücksichtigt. Die gelbe Eierwegwurf-LED ist an einen
eigenen Portpin angeschlossen. Ein kleiner Piezo-Lautsprecher ist direkt an den OC0A-Ausgang
angeschlossen. Wer gerade keinen Piezo da hat, kann auch einen kleinen 32-Ohm-Lautsprecher
anschließen, dann aber über einen 100 µF-Elko gleichstrommäßig entkoppeln!

An den Seitenanfang

Funktionsweise

Prozessorsteuerung

Die Schaltung kann wegen der niedrigen Versorgungsspannung


nicht per ISP programmiert werden, die LEDs würden kaputt
gehen! Also den Prozessor auf einem externen Board
programmieren und fertig programmiert in die Schaltung
einsetzen.

Der Prozessor wird zuerst per Fuse-Programmierung auf den


internen RC-Oszillator von 4 MHz umgestellt, wir wollen ja
möglichst Strom sparen. Die DIV8-Fuse bleibt aktiviert, so dass
er mit 500 kHz Takt läuft. Langsam genug für die V-Version.

Der Assembler-Quellcode ist hier zum Download verfügbar, in


html-Format hier.

Im Quellcode werden zuerst die Portpins zugeordnet. D.h., dass


alle LEDs in beliebiger Reihenfolge montiert und den Portpins
zugeordnet werden können. Die Reihenfolge muss dann dem
richtigen Port, Richtungsport und Portbit zugeordnet werden. Die
etwas aufwändige Programmierung der einzelnen Ein- und
Ausschaltroutinen für jede einzelne LED am Ende des Codes ist
dieser Schaltfreiheit zu verdanken.

Die Zeitmessung und die LED-Laufanzeige erfolgt mit dem 16-Bit-


Timer 1, der im CTC-Mode läuft. Beim Erreichen des im Compare-
Registers A eingestellten Werts wird alle 0,2 Sekunden ein
Interrupt ausgelöst und die T-Flagge im Status-Register gesetzt.
Der Interrupt weckt den schlafenden Prozessor auf, der danach
das T-Flag prüft. Bei gesetztem Flag wird dieses zurückgesetzt
und das niedrigste Bit des LED-Zählers abgefragt. Ist dieses
Eins, wird der Ton des Lautsprechers abgeschaltet. Bei Null wird
geprüft, ob noch ein Piepton auszugeben ist. Wenn ja, wird der
Lautsprecherton eingeschaltet (Timer 0 aktiviert) und die Anzahl
noch auszugebender Piepser um einen verringert.

Danach wird die zuletzt eingeschaltete LED ausgeschaltet. Der


LED-Zähler wird erhöht und geprüft, ob er die 10 überschritten
hat. Wenn ja, wird der Sekundenzähler erhöht und geprüft, ob
dieser 30 erreicht hat. Wenn ja, ist eine Minute um, der
Minutenzähler wird erhöht und geprüft, ob er 10 überschritten
hat. Wenn ja, wird die gelbe LED eingeschaltet und der
Dauerpieps eingeschaltet.

Abschließend wird die nächste LED ermittelt und je nach Stand


des Minutenzählers entweder auf rot oder auf grün geschaltet.
Die einzuschaltende Lampe wird dazu zur Anfangsadresse der
Sprungtabelle (rot bzw. grün) im Registerpaar ZH:ZL addiert und
mit IJMP in die Tabelle gesprungen. Alle Schaltroutinen
verzweigen am Ende wieder zum Schlafbefehl der
Hauptprogrammschleife.

Varianten

Es gibt eine breite Palette an Varianten:


1. Bandgeschwindigkeit:
❍ für Hektiker: ihm geht das alles zu langsam, für ihn verdoppeln wir die Laufgeschwindigkeit

der LEDs auf das Doppelte, indem wir den Wert von 12500 auf 6250 herabsetzen und die 30
aus der Minutenerkennung auf 60 verstellen. Das gibt Speed.
❍ für den Nachdenklichen: ihm kann es nicht langsam genug gehen, bis er die Farbe einer LED

zuverlässig einschätzen kann, braucht er fast eine halbe Sekunde. Also machen wir aus 12500
mal eben 25000 und aus 30 wird 15.
2. LEDs verkehrt herum montiert? Kein Problem: die Zeilen
ldi ZH,HIGH(TabRot) ; versuche es mit rot, und
ldi ZL,LOW(TabRot)
gegen die Zeilen
ldi ZH,HIGH(TabGruen) ; nein, es ist gruen, und
ldi ZL,LOW(TabGruen)
vertauschen und schon läuft es mit umgekehrten Farben.
3. Lieber hochtönend? Kein Problem, in der Zeile
ldi rmp,63 ; CTC-Wert
die 63 gegen einen niedrigeren CTC-Wert für Timer 0 auswählen.
4. Eieruhr für Musikliebhaber? Geht! Tabelle mit den CTC-Werten für die Tonleiter im Flash anlegen,
nach jeder beendeten Minute den zugehörigen CTC-Wert aus der Tabelle lesen und in das Compare-
Register A des Timers 0 schreiben.
5. Wer lieber ganz, ganz harte Eier vom Typus "Grünkern-Golfball" mag: vier weitere Duo-LEDs an
die noch freien Portpins klemmen und die Software um die weiteren vier LEDs erweitern.
6. ...

Der Variantenreichtum macht es unmöglich, den Quellcode für alle Varianten hier fertig anzubieten. Die
Anzahl dürfte auch bei großem Bekanntenkreis ausreichen, dass keine zwei Uhren mit demselben Design
verschenkt werden müssen, jedem sein eigenes Spielzeug.

Viel Erfolg beim Basteln.

An den Seitenanfang

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr.html1/20/2009 7:40:57 PM
http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr.gif

http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr.gif1/20/2009 7:41:08 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/eieruhr.asm

; **************************************************
; * ATtiny2313-Eieruhr, Version 1, 20.10.2006 *
; * (C)2006 by G.Schmidt info@avr-asm-tutorial.net *
; **************************************************
;
.NOLIST
.INCLUDE "tn2313def.inc"
.LIST
;
; ***************************************
; Fuses-Voreinstellungen im ATtiny2313V
; ***************************************
;
; - Internen RC-Oszillator auf 4 MHz, CLKSEL3:0 = 0010, SUT1:0 = 10
; - Interner Clockteiler auf 8, CKDIV8 = Enabled
;
; ***************************************
; Hardware - Schaltung
; ***************************************
;
; __________
; / |_| |
; +3V O--|Res VCC|--O +3V
; | |
; L1K O--|PD0 PB7|--O L10A
; | |
;L1A/L2K O--|PD1 PB6|--O L9A/L10K
; | AT |
; O--|PA1 PB5|--O L8A/L9K
; | tiny |
; O--|PA0 PB4|--O L7A/L8K
; | 2313 |
;L2A/L3K O--|PD2 PB3|--O
; | V |
;L4K/L3A O--|PD3 PB2|--||--O Lsp
; | (OC0A)|
;L5K/L4A O--|PD4 PB1|--O
; | |
;L6K/L5A O--|PD5 PB0|--O L0K
; | |
; GND O--|GND PD6|--O L6A/L7K
; |___________|
;
;
; ***************************************
; Definiere Ports und Portbits
; ***************************************
;
.EQU pOcO = PORTB
.EQU dOcO = DDRB
.EQU bOcO = 2
;
.EQU pL0K = PORTB
.EQU dL0K = DDRB
.EQU bL0K = 0
;
.EQU pL1K = PORTD
.EQU dL1K = DDRD
.EQU bL1K = 0
;
.EQU pL1A = PORTD
.EQU dL1A = DDRD
.EQU bL1A = 1
;
.EQU pL2K = PORTD
.EQU dL2K = DDRD
.EQU bL2K = 1
;
.EQU pL2A = PORTD
.EQU dL2A = DDRD
.EQU bL2A = 2
;
.EQU pL3K = PORTD
.EQU dL3K = DDRD
.EQU bL3K = 2
;
.EQU pL3A = PORTD
.EQU dL3A = DDRD
.EQU bL3A = 3
;
.EQU pL4K = PORTD
.EQU dL4K = DDRD
.EQU bL4K = 3
;
.EQU pL4A = PORTD
.EQU dL4A = DDRD
.EQU bL4A = 4
;
.EQU pL5K = PORTD
.EQU dL5K = DDRD
.EQU bL5K = 4
;
.EQU pL5A = PORTD
.EQU dL5A = DDRD
.EQU bL5A = 5
;
.EQU pL6K = PORTD
.EQU dL6K = DDRD
.EQU bL6K = 5
;
.EQU pL6A = PORTD
.EQU dL6A = DDRD
.EQU bL6A = 6
;
.EQU pL7K = PORTD
.EQU dL7K = DDRD
.EQU bL7K = 6
;
.EQU pL7A = PORTB
.EQU dL7A = DDRB
.EQU bL7A = 4
;
.EQU pL8K = PORTB
.EQU dL8K = DDRB
.EQU bL8K = 4
;
.EQU pL8A = PORTB
.EQU dL8A = DDRB
.EQU bL8A = 5
;
.EQU pL9K = PORTB
.EQU dL9K = DDRB
.EQU bL9K = 5
;
.EQU pL9A = PORTB
.EQU dL9A = DDRB
.EQU bL9A = 6
;
.EQU pL10K = PORTB
.EQU dL10K = DDRB
.EQU bL10K = 6
;
.EQU pL10A = PORTB
.EQU dL10A = DDRB
.EQU bL10A = 7
;
; ***************************************
; Funktionsweise Timing
; ***************************************
;
; Timer1 = Zeitmessung
; _______ ______ ______ ______ _____ ______
; |RC-Osc.| | CDiv |500|Presc.|62,5|TC1CNT|5Hz| LED |0,5|MinCnt|
; | 4 MHz |===>| / 8 |==>| / 8 |===>|/12500|==>|Count|==>| / 30 |==>1 Min.
; |_______| |______|kHz|______|kHz |______| |_____|Hz |______|
; |
; Timer0 = NF-Erzeugung|
; | ______ ______
; | |Presc.| |TC0CNT|992Hz
; |=>| / 8 |==>| / 63 |===> OC0A = Beep-Lautsprecher
; |______| |______|
;
;
; ***************************************
; Register
; ***************************************
;
.DEF rmp = R16
.DEF rFlg = R17
.DEF rLed = R18
.DEF rSec = R19
.DEF rMin = R20
.DEF rNb = R21
;
; ***************************************
; Reset und Interrupt-Vektoren
; ***************************************
;
.CSEG
.ORG $0000
rjmp Main ; Reset
reti ; INT0 Interrupt
reti ; INT1 Interrupt
reti ; TC1Capt Interrupt
rjmp TC1CmpA ; Timer 1 Compare A match
reti ; TC1 Overflow Int
reti ; TC0 Overflow Int
reti ; UART0 RX Int
reti ; UART0 TX Int
reti ; Ana Comp Int
reti ; PCINT
reti ; TC1 CompB Int
reti ; TC0 Compare Match A Int
reti ; TC0 Compare Match B Int
reti ; USISTART Int
reti ; USIOverflow Int
reti ; EERDY Int
reti ; WDT Overflow Int
;
; ***************************************
; TC1 Compare Match A Interrupt Routine
; ***************************************
;
TC1CmpA:
set
reti
;
; ***************************************
; Hauptprogramm
; ***************************************
;
Main:
; Stack init
ldi rmp,LOW(RAMEND) ; Setze Stackpointer
out SPL,rmp
; Init Register
ldi rFlg,0 ; Init Flagge
ldi rLed,0 ; Init LEDs
ldi rSec,0 ; Init Sekundenzaehler
ldi rMin,1 ; Init Minutenzaehler
ldi rNb,1 ; Init Beep-Zaehler
; Init OCR0A-Output fuer Beep
sbi dOcO,bOcO
; Init Timer 1 fuer Zeit- und Lampensteuerung
ldi rmp,HIGH(12500) ; CTC-Wert
out OCR1AH,rmp
ldi rmp,LOW(12500)
out OCR1AL,rmp
clr rmp ; Kontrollwort A
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; auf CTC
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; Timer1-Interrupt
out TIMSK,rmp
; Init Timer 0 fuer Beep-Ausgang
ldi rmp,(1<<COM0A0)|(1<<WGM01) ; CTC, Toggle Compare A
out TCCR0A,rmp
ldi rmp,1<<CS01 ; beep an
out TCCR0B,rmp
ldi rmp,63 ; CTC-Wert
out OCR0A,rmp
ldi rmp,1<<SE ; sleep idle
out MCUCR,rmp
sei ; Enable Ints
;
; ***************************************
; Hauptprogramm - Loop
; ***************************************
;
; in Schlafmodus gehen
An:
sleep ; Schlafen
nop ; Aufwachen
brtc An ; T-Flag von Timer nicht gesetzt
clt ; T-Flag zuruecksetzen
sbrc rLed,0 ; Bit 0 ist Beep-Steuerung
rjmp BeepAus
tst rNb ; teste beeps = 0
breq BeepAus ; schalte Beep aus
ldi rmp,1<<CS01 ; beep an
out TCCR0B,rmp
dec rNb ; verringere Beeps
rjmp LedAus
BeepAus:
ldi rmp,0 ; Beep ausschalten, Timer stoppen
out TCCR0B,rmp
LedAus:
ldi ZH,HIGH(TabAus) ; LED ausschalten
ldi ZL,LOW(TabAus)
add ZL,rLed ; aktuelle LED addieren
brcc MachAus
inc ZH
MachAus:
ijmp ; aktuelle LED deaktivieren
Aus: ; LED ist ausgeschaltet
inc rLed ; erhoehe Zaehler
cpi rLed,10 ; schon bei Zehn?
brne Weiter ; nein
clr rLed ; ja, von vorne beginnen
inc rSec ; 0,5-Sekundenzaehler erhoehen
cpi rSec,30 ; schon bei 30?
brcs Weiter ; nein, noch nicht
clr rSec ; ja, loesche 0,5-Sekundenzaehler
mov rNb,rMin ; Minuten in Beep-Zaehler kopieren
inc rMin ; Minutenzaehler erhoehen
cpi rMin,11 ; 10 Minuten abgelaufen?
brcs Weiter ; nein
clr rMin ; Mintenzaehler von vorne
ldi rNb,255 ; Beep fuer ganze Minute an
sbi dL0K,bL0K ; Ausgang gelbe Lampe an
cbi pL0K,bL0K ; gelbe Lampe an
Weiter: ; aktuelle LED rot oder gruen?
ldi ZH,HIGH(TabRot) ; versuche es mit rot
ldi ZL,LOW(TabRot)
cp rLed,rMin ; aktuelle LED kleiner als Minutenzaehler
brcs Weiter1 ; nein
ldi ZH,HIGH(TabGruen) ; nein, es ist gruen
ldi ZL,LOW(TabGruen)
Weiter1: ; Lampe anschalten
add ZL,rLed ; mache die richtige LED an
brcc MachAn
inc ZH
MachAn: ; schalte Lampe an
ijmp
;
; ***************************************
; Sprungtabellen
; ***************************************
;
; Sprungtabelle der Lampen-Routinen fuer Rot
TabRot:
rjmp L1R
rjmp L2R
rjmp L3R
rjmp L4R
rjmp L5R
rjmp L6R
rjmp L7R
rjmp L8R
rjmp L9R
rjmp L10R
; Sprungtabelle der Lampen-Routinen fuer Gruen
TabGruen:
rjmp L1G
rjmp L2G
rjmp L3G
rjmp L4G
rjmp L5G
rjmp L6G
rjmp L7G
rjmp L8G
rjmp L9G
rjmp L10G
; Sprungtabelle der Lampen-Routinen fuer Ausschalten
TabAus:
rjmp L1A
rjmp L2A
rjmp L3A
rjmp L4A
rjmp L5A
rjmp L6A
rjmp L7A
rjmp L8A
rjmp L9A
rjmp L10A
;
; ***************************************
; Lampen - Schaltroutinen
; ***************************************
;
; Lampen ausschalten
L1A:
cbi pL1A,bL1A
cbi pL1K,bL1K
cbi dL1A,bL1A
cbi dL1K,bL1K
rjmp Aus
L2A:
cbi pL2A,bL2A
cbi pL2K,bL2K
cbi dL2A,bL2A
cbi dL2K,bL2K
rjmp Aus
L3A:
cbi pL3A,bL3A
cbi pL3K,bL3K
cbi dL3A,bL3A
cbi dL3K,bL3K
rjmp Aus
L4A:
cbi pL4A,bL4A
cbi pL4K,bL4K
cbi dL4A,bL4A
cbi dL4K,bL4K
rjmp Aus
L5A:
cbi pL5A,bL5A
cbi pL5K,bL5K
cbi dL5A,bL5A
cbi dL5K,bL5K
rjmp Aus
L6A:
cbi pL6A,bL6A
cbi pL6K,bL6K
cbi dL6A,bL6A
cbi dL6K,bL6K
rjmp Aus
L7A:
cbi pL7A,bL7A
cbi pL7K,bL7K
cbi dL7A,bL7A
cbi dL7K,bL7K
rjmp Aus
L8A:
cbi pL8A,bL8A
cbi pL8K,bL8K
cbi dL8A,bL8A
cbi dL8K,bL8K
rjmp Aus
L9A:
cbi pL9A,bL9A
cbi pL9K,bL9K
cbi dL9A,bL9A
cbi dL9K,bL9K
rjmp Aus
L10A:
cbi pL10A,bL10A
cbi pL10K,bL10K
cbi dL10A,bL10A
cbi dL10K,bL10K
rjmp Aus
; Lampe auf Gruen
L1G:
sbi pL1A,bL1A
cbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2G:
sbi pL2A,bL2A
cbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3G:
sbi pL3A,bL3A
cbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4G:
sbi pL4A,bL4A
cbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5G:
sbi pL5A,bL5A
cbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6G:
sbi pL6A,bL6A
cbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7G:
sbi pL7A,bL7A
cbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8G:
sbi pL8A,bL8A
cbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9G:
sbi pL9A,bL9A
cbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10G:
sbi pL10A,bL10A
cbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
; Lampe auf Rot
L1R:
cbi pL1A,bL1A
sbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2R:
cbi pL2A,bL2A
sbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3R:
cbi pL3A,bL3A
sbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4R:
cbi pL4A,bL4A
sbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5R:
cbi pL5A,bL5A
sbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6R:
cbi pL6A,bL6A
sbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7R:
cbi pL7A,bL7A
sbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8R:
cbi pL8A,bL8A
sbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9R:
cbi pL9A,bL9A
sbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10R:
cbi pL10A,bL10A
sbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
;
; Ende des Quellcodes
;

http://www.avr-asm-tutorial.net/avr_de/quellen/eieruhr.asm1/20/2009 7:41:10 PM
Quellcode Schrittmotor-Steuerung mit ATtiny13

Pfad: Home => AVR-Übersicht => Anwendungen => Steppermotor-Steuerung => Quellcode

Quellcode der
Schrittmotor-
Steuerung mit
ATtiny13

; ***************************************************
; * Schrittmotor-Steuerung mit ATtiny13 - Version 1 *
; * (C)2007 by http://www.avr-asm-tutorial.net *
; ***************************************************
;
; Debugging switches
;
.equ debug_calc = 0
.equ debug_const = 0
.equ debug_out = 0
;
.nolist
.include "tn13def.inc"
.list ; ______
; / |
; Hardware: | |
; _______ . . +12V schwarz
; ___ / | | | ___ |
; +5V-|___|--|RES VCC|--+5V B3-|I4 O4|-|___|-+Q4 rot
; | | | | ___ |
; B3--|PB3 PB2|---------|I5 O5|-|___|-+Q2 braun
; | | | | ___ |
; Analog-In--|PB4 PB1|---------|I6 O6|-|___|-+Q3 gruen
; | | | | ___ |
; |--|GND PB0|---------|I7 O7|-|___|-+Q1 weiss
; |________| | | |
; ATtiny13 |-|GND CD|-------+
; |_______|
; ULN2003
;
; Funktionsweise:
; Ein Schrittmotor wird mit einer analogen Eingangs-
; spannung an Pin 3 gesteuert. Die Eingangsspannung
; liegt zwischen Null und der Betriebsspannung. Die
; Anzahl Einzelschritte des Motor fuer Vollausschlag
; sind mit der Konstanten cSmSteps einstellbar (1...
; 65535 Schritte).
; Ansteuerung Schrittmotor:
; Portbit PB0 PB2 PB1 PB3 | |
; Farbe ws bn gn rt | Port | Byte
; Schritt Q4 Q3 Q2 Q1 | 3 2 1 0 |
; ------------------------+---------+------
; 1 1 1 0 0 | 0 1 0 1 | 05
; 2 0 1 1 0 | 0 1 1 0 | 06
; 3 0 0 1 1 | 1 0 1 0 | 0A
; 4 1 0 0 1 | 1 0 0 1 | 09
; entspricht: .dw 0x0605,0x090A
;
; Timer TC0:
; Timer läuft bei einem Prozessortakt von 1,2 MHz mit
; einem Vorteiler von 1024 im CTC-Modus mit CompareA
; als TOP-Wert. Interrupt bei CompareA bzw. beim
; CTC-Reset.
; Bei CompareA wird der Soll- und Ist-Wert des
; Schrittmotors verglichen. Ist der Ist-Wert zu
; hoch, wird ein Schritt zurueck gefahren, ist
; der Ist-Wert zu niedrig, wird ein Schritt vor-
; waerts gefahren. Stimmen Soll- und Ist-Wert
; ueberein, werden nach einer einstellbaren Verzoe-
; gerung die Magnete des Schrittmotor abgeschaltet
; Timing: 1,2 MHz / 1024 / CompA,
; bei CompA = 255: f(Schrittmotor) = 4,57 Hz
; bei CompA = 8 : f(Schrittmotor) = 146 Hz
; ADC:
; Umwandlung der an Pin 3 / PB4 /ADC2 anliegenden
; Analogspannung, Aufsummieren von 64 Messungen
; zur Mittelung, Umrechnung in die Sollstellung
; des Schrittmotors
; Timing: 1,2 MHz / 128 = 9,375 kHz = 106,7 us
; Conversion = 13 cycles = 1,387 ms / Konversion
; = 721 Konversionen pro Sekunde
; Mittelung ueber 64 Konversionen = 88,75 ms = 11,3 / s
;
; Konstanten
;
.equ cSmSteps = 1276 ; 2552/2, Anzahl Schritte pro Umdrehung
.equ cSmFreq = 145 ; Frequenz Schrittmotorgeschwindigkeit
; ; Minimum: 5 Hz, Maximum: 1171 Hz
.equ cSmDelay = 390 ; Anzahl Takte vor Abschalten der Magnete
;
; Abgeleitete Konstanten
;
.equ clock = 1200000 ; Taktfrequenz Tiny13
.equ Tc0Ctc = 1024 ; Vorteiler TC0
.equ cCmpA = clock / 1024 / cSmFreq
;
; Ueberpruefung der Konstanten
;
.IF cCmpA > 255
.ERROR "Schrittmotor zu langsam!"
.ENDIF
.IF cCmpA < 1
.ERROR "Schrittmotor zu schnell!"
.ENDIF
;
; SRAM
;
; Register
;
; benutzt: R0 fuer Tabellenlesen
; benutzt: R8:R1 fuer Rechnen
; frei: R10:R8
.def rAdcCL = R11 ; ADC Rechenwert LSB
.def rAdcCH = R12 ; dto., MSB
.def rAdcRL = R13 ; ADC Uebergabe LSB
.def rAdcRH = R14 ; dto., MSB
.def rSreg = R15 ; Status Sicherungs-Register
.def rmp = R16 ; Multipurpose outside Int
.def rimp = R17 ; Multipurpose inside Int
.def rFlg = R18 ; Flaggen
.equ bAdc = 0 ; Adc conversion complete flag
.def rAdcC = R19 ; ADC Zaehler (64 Adc-Werte)
.def rAdcL = R20 ; ADC Addier-Register LSB
.def rAdcH = R21 ; dto., MSB
.def rSmSL = R22 ; Stepmotor-Sollwert LSB
.def rSmSH = R23 ; dto., MSB
.def rSmIL = R24 ; Stepmotor-Istwert LSB
.def rSmIH = R25 ; dto., MSB
; benutzt: X fuer Nachlauf der Magnete
; frei: Y
; benutzt: Z fuer Tabellenwert-Zugriff
;
; **********************************
; Code Segment Start, Int - Vektor
; **********************************
;
.cseg
.org $0000
;
rjmp Main ; Reset Vektor
reti ; INT0 Vektor
reti ; PCINT0 Vektor
reti ; TIM0_OVF Vektor
reti ; EE_RDY Vektor
reti ; ANA_COMP Vektor
rjmp Tc0IntCA ; TIM0_COMPA Vektor
reti ; TIM0_COMPB Vektor
reti ; WDT Vektor
rjmp AdcInt ; ADC Vektor
;
; **********************************
; Interrupt Service Routinen
; **********************************
;
; Timer-Counter 0 Compare A Interrupt Service Routine
;
Tc0IntCA:
in rSreg,SREG ; rette Status
cp rSmIL,rSmSL ; vergleiche Ist mit Soll
cpc rSmIH,rSmSH
breq Tc0IntCA0
brcs Tc0IntCAF ; Ist < Soll
sbiw rSmIL,1 ; Ist > Soll, ein Schritt rueckwaerts
rjmp Tc0IntCAS
Tc0IntCAF:
adiw rSmIL,1 ; ein Schritt vorwaerts
Tc0IntCAS:
mov rimp,rSmIL ; kopiere Zaehlerstand
andi rimp,0x03 ; isoliere unterste zwei Bits
ldi ZH,HIGH(2*SmTab) ; Zeige auf Tabelle
ldi ZL,LOW(2*SmTab)
add ZL,rimp
ldi rimp,0
adc ZH,rimp
lpm ; lese Wert aus Tabelle
.IF debug_out == 0
out PORTB,R0 ; schreibe auf Port
.ENDIF
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
out SREG,rSreg ; Stelle Status wieder her
reti
Tc0IntCA0:
sbiw XL,1 ; Delay-Zaehler verringern
brne Tc0IntCAD ; noch nicht Null
ldi rimp,0 ; Magnete ausschalten
out PORTB,rimp ; an Ausgangstreiber
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
Tc0IntCAD:
out SREG,rSreg ; stelle Status wieder her
reti
;
SmTab:
.dw 0x0605,0x090A
;
; Adc Conversion Complete Interrupt Service Routine
;
AdcInt:
in rSreg,SREG ; rette Status
in rimp,ADCL ; lese LSB Ergebnis
add rAdcL,rimp ; addiere zum Ergebnis
in rimp,ADCH ; lese MSB Ergebnis
adc rAdcH,rimp ; addiere zum Ergebnis
dec rAdcC ; Erniedrige Zaehler
brne AdcInt1
mov rAdcRL,rAdcL ; Kopiere Ergebnis
mov rAdcRH,rAdcH
clr rAdcH ; Loesche Summe
clr rAdcL
ldi rAdcC,64 ; Setze Zaehler neu
sbr rFlg,1<<bAdc ; Setze Flagge
AdcInt1:
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|
(1<<ADPS0)
out ADCSRA,rmp
out SREG,rSreg ; stelle Status wieder her
reti
;
; **********************************
; Hauptprogramm Init und Loop
; **********************************
;
Main:
; Stack Init
ldi rmp, LOW(RAMEND)
out SPL,rmp
; Init Register
clr rFlg ; Flag-Register auf Null
clr rSmIL ; Ist-Zaehler Stepmotor auf Null
clr rSmIH
clr rSmSL ; Soll-Wert Stepmotor auf Null
clr rSmSH
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
; Init Output-Port
ldi rmp,0x0F ; Ausgabe auf Port 0 is 3
out DDRB,rmp
ldi rmp,0x05 ; Schrittmotor auf Schritt 1 setzen
out PORTB,rmp
; Debugging session
.IF debug_calc
.equ adc_result = 128
ldi rmp,HIGH(adc_result)
mov rAdcRH,rmp
ldi rmp,LOW(adc_result)
mov rAdcRL,rmp
rjmp dcalc
.ENDIF
.IF debug_const
.equ const = cMSteps
ldi rmp,HIGH(const)
mov rSmSH,rmp
ldi rmp,LOW(const)
mov rSmSL,rmp
.ENDIF
; Init ADC
ldi rAdcC,64 ; Setze Zaehler neu
clr rAdcL ; Setze Ergebnis auf Null
clr rAdcH
ldi rmp,1<<ADC2D ; Digital Input Disable
out DIDR0,rmp
ldi rmp,1<<MUX1 ; ADC auf Kanal 2
out ADMUX,rmp
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|
(1<<ADPS0)
out ADCSRA,rmp
; TC0 initiieren
ldi rmp,cCmpA ; CTC-Wert setzen
out OCR0A,rmp
ldi rmp,1<<WGM01 ; CTC-Mode
out TCCR0A,rmp
ldi rmp,(1<<CS02)|(1<<CS00) ; Prescaler = 1024
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Interrupt Compare Match A enable
out TIMSK0,rmp
; Sleep Mode und Int Enable
ldi rmp,1<<SE ; Schlafen Enable
out MCUCR,rmp
sei ; Int Enable
Loop:
sleep ; schlafen
nop ; Dummy fuer Aufwachen
sbrc rFlg,bAdc ; ADC-Flagge?
rcall AdcRdy ; wandle ADC-Ergebnis um
rjmp Loop
;
; **********************************
; Rechenroutinen
; **********************************
;
; ADC Umwandlungs-Egebnis fertig
;
AdcRdy:
cbr rFlg,1<<bAdc ; setze Flagge zurueck
.IF debug_const
ret
.ENDIF
dcalc:
mov rAdcCH,rAdcRH ; kopiere Messwert
mov rAdcCL,rAdcRL
ldi rmp,LOW(cSmSteps) ; Anzahl Schritte in R4:R3:R2:R1
mov R1,rmp
ldi rmp,HIGH(cSmSteps)
mov R2,rmp
clr R3
clr R4
clr R5 ; Ergebnis in R8:R7:R6:R5 loeschen
clr R6
clr R7
clr R8
AdcRdy1:
lsr rAdcCH ; ein Bit herausschieben
ror rAdcCL
brcc AdcRdy2 ; nicht addieren
add R5,R1 ; addieren
adc R6,R2
adc R7,R3
adc R8,R4
AdcRdy2:
lsl R1 ; Multiplikator mal zwei
rol R2
rol R3
rol R4
mov rmp,rAdcCL ; = Null?
or rmp,rAdcCH
brne AdcRdy1 ; weiter multiplizieren
ldi rmp,0x80 ; aufrunden
add R5,rmp
adc R6,rmp
ldi rmp,0
adc R7,rmp
adc R8,rmp
cli ; Interrupts aus
mov rSmSL,R7 ; Stepmotor-Sollwert LSB
mov rSmSH,R8 ; dto., setze MSB
.IF debug_out
out PORTB,rSmSL
.ENDIF
sei ; Interrupts wieder an
ret
;
; Ende Source Code
;

©2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/stepper/schrittmotor_v1.html1/20/2009 7:41:15 PM
Schrittmotor-Steuerung mit ATtiny13

Pfad: Home => AVR-Übersicht => Anwendungen => Steppermotor-Steuerung

Schrittmotor-Steuerung mit ATtiny13


Diese Anwendung eines AVR beschreibt die Steuerung eines Schrittmotors mit einem ATMEL
ATtiny13 mit folgenden Eigenschaften:

● Konzipiert für die Fernsteuerung von Schrittmotoren mit Getriebe.


● Eine Eingangsspannung von 0..5 V mit einer Auflösung von 10 Bits (1024 auflösbare Schritte, Schrittweite: 4,88 mV) steuert die Stellung des
Schrittmotors.
● Anzahl der gesamten Schrittanzahl bis 65.535 einstellbar, daher nahezu beliebige Getriebeübersetzungen per Software einstellbar.
● Einfachste Ansteuerung des Schrittmotors.
● Sehr schnelle Einstellung durch optimale Anpassbarkeit an die maximale Drehgeschwindigkeit des Motors.
● Optimale Reduzierung des Strombedarfs durch Abschaltung der Spulen nach Verstellung.

0. Inhalt
● 1. Hardware
❍ 1.1 Prozessorteil

❍ 1.2 ISP-Interface

❍ 1.3 Spulentreiber ULN2003A

❍ 1.4 Stromversorgung

● 2. Software
❍ 2.1 Funktionsweise

❍ 2.2 Einstellungen vor dem Assemblieren

❍ 2.3 Kommentierter Quellcode

1. Hardware
Die Hardware besteht aus dem AVR-Prozessor ATtiny13, einem
sechspoligen Standard-In-System-Programmieranschluss (ISP), einem 7-Bit-
Treiber ULN2003, der Stromversorgung für den Prozessor und der Filterung
der Eingangsspannung. Das Schaltbild (Anklicken für höher aufgelöstes PDF-
Format):

1.1 Prozessorteil

Der Prozessor ATtiny13 hat folgende Funktionen.


Die Betriebsspannung von 5 V wird über die Pins 8 (+5 V) und 4 (0 V) zugeführt und mit einem Keramikkondensator von 100 nF abgeblockt.
Pin 1 (= RESET-Eingang) liegt über einen Widerstand von 10 kOhm an der positiven Betriebsspannung.
Der Eingang PB4 (Pin 3) misst über einen internen AD-Wandler die anliegende Analogspannung durch Vergleich mit der Betriebsspannung. Die Software
errechnet daraus die Soll-Stellung des Schrittmotors.
Die Ausgänge PB0 bis PB3 (Pins 5, 6, 7 und 2) steuern die Treiber für die Schrittmotor-Magnete an.

1.2 ISP-Interface

Das ISP-Interface dient der Programmierung des AVR in der fertig aufgebauten Schaltung. Die Beschaltung entspricht dem ATMEL-Standard.
Für ISP verwendet werden die Portbits PB2 (SCK, Pin 7), PB1 (MISO, Pin 6), PB0 (MOSI, Pin 5) sowie der RESET an Pin 1 verwendet. Die
Betriebsspannungsanschl sse VTG und GND versorgen eventuell das externe ISP-Interface, hat dies eine eigene Versorgung ist VTG offen zu lassen.

1.3 Spulentreiber ULN2003A

Die Antriebsströme für die Magnete des Schrittmotors werden vom Treiberbaustein ULN2003A gesteuert. Die Ausgänge mit Open-Collector-
Treibertransistoren vertragen hohe Spannungen von 50 V, Ströme bis 500 mA und schalten die einzelnen Magnete des Motors ein und aus.
Induktive Überspannungen an den Kollektoren werden über die eingebauten Dioden am Anschluss CD kurzgeschlossen. Der hier verwendete Motor wird mit
12 V Betriebsspannung betrieben und zieht pro Magnet ca. 150 mA Strom (da im Betrieb immer zwei Magnete angesteuert werden zusammen 300 mA).
Die Eingänge I7..I4 des Treiberbausteins werden vom Prozessor angesteuert (aktiv high, logisch 1 schaltet Magnet an).

1.4 Stromversorgung

Bei der Stromversorgung auf der Steuerung wurde auf eine hohe Festigkeit gegenüber den Schaltströmen der Magnete gelegt. Die Versorgung der Magnete
erfolgt gegen Verpolung über eine Diode 1N4007 mit einem Glättungskondensator von 100 µF.
Der Prozessor wird über eine eigene 5 V-Versorgung betrieben, die mit einer Diode 1N4007 und einem Glättungskondensator von 100 µF aus der 12 V-
Versorgung abgeleitet ist. Der Spannungsregler 78L05 ist mit Tantalkondensatoren von 1 µF bzw. 2,2 µF gegen Schwingungen gesichert.
Die Versorgung der Steuerung erfolgt über ein vieradriges Kabel aus einem 12 V-Netzteil (Klick auf Bild fürt zu höher aufgelöstem PDF-Dokument).

Die Stromversorgung ist auf einer kleinen Leiterplatte aufgebaut.

2. Software
Die Software für den ATtiny13 ist in Assembler geschrieben, der Quellcode ist hier erhältlich.

2.1 Funktionsweise

Die Software besteht aus folgenden Grundelementen:

● der Reset- und Interruptvektor-Tabelle,


● der Initiierung der Anfangswerte und der Hardwarekomponenten,
● der AD-Wandler-Messung der Eingangsspannung,
● der Umrechnung des Ergebnisses in den Sollwert,
● der Schrittsteuerung und der Ausgabe an den Schrittmotor.

Reset- und Interruptvektor-Tabelle

Die Vektortabelle verzweigt bei einem Reset zum Hauptprogramm, bei den beiden Interrupts des Timer/Counters und des AD-Wandlers zu den entsprechenden
Behandlungsroutinen. Nicht verwendete Vektoren sind mit RETI abgeschlossen.

Iniitierung Anfangswerte

Die Initiierung der Anfangswerte erfolgt ab dem Label "Main:". Hier wird

● der Stapel initiiert, da mit Interrupts und Unterprogrammen gearbeitet wird,


● das Flaggenregister gelöscht (Funktion siehe unten),
● der Soll- und Ist-Wert des Schrittmotors auf Null gesetzt,
● der Abschaltzähler gesetzt.

Initiierung Hardware

Die Initiierung der Hardware umfasst:

● die Richtung der vier Portbits PB0 bis PB3 als Ausgang und die Bits auf den ersten Schritt des Steppermotors setzen,
● den Zähler für den AD-Wandler auf 64 setzen, das Summenergebnis der Wandlungen löschen, den Digitaleingang von PB4=ADC2 abschalten (wird
nicht benötigt, PB4 dient ausschließlich der AD-Messung), die AD-Wandler-Mux fest auf Kanal ADC2 einstellen, und den AD-Wandler mit folgenden
Einstellungen starten:
❍ Referenzspannung ist die Betriebsspannung des ATtiny13,

❍ Taktteiler=128, bei 1,2 MHz internem Takt und 13 Taktzyklen pro Messung braucht jede Messung 1,387 ms, Aufsummieren von jeweils

64 Messungen ergibt einen fertigen Messwert alle 88,75 ms oder 11,3 Messwerte pro Sekunde.
❍ Interrupt nach jeder abgeschlossenen Messung,

❍ kein automatischer Neustart der nächsten Messung (wird beim Interrupt neu gestartet).

● der Timer/Counter 0 wird auf normalen CTC-Modus (Löschen des Zählers bei Erreichen des Vergleichswerts) eingestellt, mit folgenden Eigenschaften:
❍ die Dauer eines CTC-Zyklus ist so lange wie die Ausgabe für einen Schritt des Motors dauert und wird durch die Konstante cCmpA bestimmt, die

in das Compare-Register A des Counters geschrieben wird,


❍ nach jedem CTC-Zyklus wird ein Interrupt ausgelöst, der Compare-Match-Interrupt A wird ermöglicht,

❍ der Vorteiler wird auf 1024 eingestellt, der Counter-Takt beträgt daher 1,2 MHz/1024 = 1,172 kHz, mit CTC-Werten zwischen 1 und 255 ergeben

sich Frequenzen zwischen 1172 und 4,6 Hz für die Ansteuerung des Schrittmotors.
● der Prozessor wird auf Schlafmodus eingestellt, d.h. zwischen den Interrupts des Counters und des AD-Wandlers ist der Programmablauf unterbrochen.

AD-Wandler-Messung der Eingangsspannung

Der AD-Wandler wandelt die Eingangsspannung an Pin 3 (PB4, ADC2) in einen Wert zwischen 0..1023 um und löst nach jedem Abschluss der Wandlung
einen Interrupt aus. Die Interrupt-Behandlungsroutine ab dem Label "AdcInt:" holt das Ergebnis von den Ports ADCL und ADCH ab und summiert es 16-bittig
zu dem Registerpaar rAdcH:rAdcL. Der Zähler rAdc wird um eins herangezählt. Erreicht er Null, dann wird die bis dahin erreichte Summe in das Registerpaar
rAdcRH:rAdcRL kopiert, die Summe wieder auf Null gesetzt, der Zähler wieder auf den Anfangswert 64 und die Flagge bAdc im Flaggenregister gesetzt.
Abschließend wird der AD-Wandler erneut gestartet.
Der Summiervorgang bewirkt, dass jeweils 64 Messwerte gemittelt werden, wodurch absichtlich der Ablauf verlangsamt und die Messung von zufälligen und
durch Einstreuung verursachten Schwankungen unabhängiger wird. Der resultierende Summenwert liegt zwischen Null und 65535 (0x0000..0xFFFF).

Umrechnung des Messergebnisses in den Sollwert

Ist nach einem Interrupt die Flagge bAdc im Flaggenregister gesetzt, wird die Umrechnungsroutine ab dem Label "AdcRdy:" aufgerufen. Diese

● löscht das Flaggenbit wieder,


● kopiert den Summenwert in das Registerpaar rAdcCH:rAdcL,
● multipliziert den Summenwert mit der Konstanten cSmSteps (der Anzahl Schritte, die der Schrittmotor bei Vollausschlag in Vorwärtsrichtung machen
soll), zu einem 32-Bit-Ergebnis,
● rundet die untersten 16 Bits,
● teilt das Ergebnis durch 65536, so dass sich die Sollschritte zu einem 16-Bit-Ergebnis ergeben, und
● schreibt das Ergebnis in das Soll-Registerpaar rSmSH:rSmSL (wobei Interrupts zeitweilig abgeschaltet werden, damit es nicht zu Fehlansteuerungen des
Schrittmotors kommt).

Schrittsteuerung und Ausgabe an den Schrittmotor

Die Schrittsteuerung und die Ausgabe an den Schrittmotor erfolgt in der Interrupt-Behandlungsroutine des Counters ab dem Label "Tc0IntCA:".
Zunächst wird der Ist-Wert mit dem Soll-Wert des Schrittmotors 16-bittig verglichen. Sind beide gleich, dann wird nach dem Label "Tc0IntCA0:" verzweigt.
Hier wird der Verzögerungszähler im Registerpaar X um eins verringert. Ist er Null, werden die Magnete des Schrittmotors durch Schreiben von Null auf den
Ausgabeport abgeschaltet, der Verzögerungszähler wieder auf seinen Anfangswert gesetzt und die Behandlungsroutine beendet. Ist der Ist- und Sollwert nicht
gleich, wird der Ist-Wert um einen Schritt vor- bzw. rückwärts verändert. Aus dem Ist-Wert wird der nächste Schritt des Schrittmotors ermittelt:

● die beiden untersten Bits des Ist-Wertes werden isoliert, und


● zur Anfangsadresse "SmTab:" im Flash-Speicher addiert,
● mit LPM wird der Inhalt des Bytes in das Register R0 eingelesen, und
● an den Ausgabeport geschrieben, der die Treiber der Magnetspulen des Schrittmotors ansteuert.

Die Tabelle "SmTab:" mit den beiden Worten 0x0605 und 0x090A enthält die Schrittfolge des Schrittmotors in der Reihenfolge

● Schritt 1: 0x05, binär 0 1 0 1,


● Schritt 2: 0x06, binär 0 1 1 0,
● Schritt 3: 0x0A, binär 1 0 1 0,
● Schritt 4: 0x09, binär 1 0 0 1.

Anmerkung: Sind die Spulen Q1..Q4 des Schrittmotors in anderer Reihenfolge an die Treiberausgänge angeschlossen, genügt es, diese Tabelle entsprechend
umzustellen (siehe unten). In der Behandlungsroutine wird abschließend der Verzögerungszähler wieder auf seinen Anfangswert gesetzt, um die Magnete für
die die voreingestellte Zeit im aktiven Zustand zu halten.

2.2 Einstellungen vor dem Assemblieren

Im Assembler-Quelltext sind folgende Einstellungen vor dem Assemblieren vorzunehmen:

● Die drei Debug-Schalter debug_calc, debug_const und debug_out müssen auf Null gesetzt sein!
● Die Konstante cSmSteps muss auf die Anzahl Schritte eingestellt werden, die der Schrittmotor von Null bis Vollausschlag zurücklegen soll
(Maximalwert: 65535).
● Die Konstante cSmFreq muss auf die Frequenz eingestellt werden, mit der der Schrittmotor angesteuert werden soll und die der verwendete Schrittmotor
noch gut bewältigt (minimal 5 Hz, maximal 1171 Hz).
● Die Konstante cSmDelay gibt die Anzahl Takte an, nach denen bei Erreichen des Sollwertes die Magnete des Schrittmotors weiter aktiv sein sollen. Ist
cSmDelay gleich groß wie cSmFreq, beträgt der Verzögerungszeitraum genau eine Sekunde.

Die Anschlussreihenfolge der vier Magnete an der Buchse J2 ist nicht bei allen Schrittmotoren gleich. Wird eine andere Anschlussfolge der Magnete des
Schrittmotors Q1 bis Q4 verwendet oder soll die Drehrichtung des Motors umgekehrt werden, muss nur die Tabelle SmTab: angepasst werden.
Die bestehende Tabelle für den KP4M4-001 ist folgendermaßen aufgebaut:

Magnet Farbe Portbit Step 1 Step 2 Step3 Step 4


Q1 rot PB3 0 0 1 1
Q2 grün PB1 0 1 1 0
Q3 braun PB2 1 1 0 0
Q4 weiß PB0 1 0 0 1

Daraus ergeben sich folgende Kodierungen:

Magnet Portbit
Step Byte Word
Q4 Q3 Q2 Q1 PB3 PB2 PB1 PB0
1 1 1 0 0 0 1 0 1 0x05
0x0605
2 0 1 1 0 0 1 1 0 0x06
3 0 0 1 1 1 0 1 0 0x0A
0x090A
4 1 0 0 1 1 0 0 1 0x09

2.3 Kommentierter Quellcode

Der Quellcode in .asm-Textformat ist hier erhältlich, in .html-Format hier.

©2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/stepper/stepper.html1/20/2009 7:41:41 PM
J1
AGND
100
nK 1N4007 +100µ40V
+12V
1N4007
100µ16V 78L05 +5V
Ain In Out I1 O1
100 + +1µT Gnd +2µ2T
10k
nK 36V 16V Stepper-
DGND I2 O2
J2 Motor
O3
bl KP4M4-001
1N I3
10k

4148 Q4
RST RESET VCC I4
ULN O4
rd
100nK 2003
Q2
bn
PB3 AT PB2
SCK
I5 O5

tiny Q3
13 gn
100 PB4 PB1
MISO
I6 O6
1N
nF Q1
4148 wt
MKT GND PB0
MOSI
I7 O7

GND CD
VTG MOSI GND

2 4 6
J3
ISP6
1 3 5 Steppermotor ATtiny13
MISO SCK RST
Version 1, June 2007
http://www.avr-asm-tutorial.net
J1

+1µT AGND
+1µT
Si 100mA 1N4007 36V 16V
7812
In Out +12V
J1 Gnd 1k4
12V +2200µF
0.3A 24V Ain
230V 1k
230 V
7.5VA 10-turn
12V DGND
0.3A
Steppermotor Supply
1N4007
Version 1, June 2007
http://www.avr-asm-tutorial.net
http://www.avr-asm-tutorial.net/avr_de/quellen/schrittmotor_v1.asm

; ***************************************************
; * Schrittmotor-Steuerung mit ATtiny13 - Version 1 *
; * (C)2007 by http://www.avr-asm-tutorial.net *
; ***************************************************
;
; Debugging switches
;
.equ debug_calc = 0
.equ debug_const = 0
.equ debug_out = 0
;
.nolist
.include "tn13def.inc"
.list ; ______
; / |
; Hardware: | |
; _______ . . +12V schwarz
; ___ / | | | ___ |
; +5V-|___|--|RES VCC|--+5V B3-|I4 O4|-|___|-+Q4 rot
; | | | | ___ |
; B3--|PB3 PB2|---------|I5 O5|-|___|-+Q2 braun
; | | | | ___ |
; Analog-In--|PB4 PB1|---------|I6 O6|-|___|-+Q3 gruen
; | | | | ___ |
; |--|GND PB0|---------|I7 O7|-|___|-+Q1 weiss
; |________| | | |
; ATtiny13 |-|GND CD|-------+
; |_______|
; ULN2003
;
; Funktionsweise:
; Ein Schrittmotor wird mit einer analogen Eingangs-
; spannung an Pin 3 gesteuert. Die Eingangsspannung
; liegt zwischen Null und der Betriebsspannung. Die
; Anzahl Einzelschritte des Motor fuer Vollausschlag
; sind mit der Konstanten cSmSteps einstellbar (1...
; 65535 Schritte).
; Ansteuerung Schrittmotor:
; Portbit PB0 PB2 PB1 PB3 | |
; Farbe ws bn gn rt | Port | Byte
; Schritt Q4 Q3 Q2 Q1 | 3 2 1 0 |
; ------------------------+---------+------
; 1 1 1 0 0 | 0 1 0 1 | 05
; 2 0 1 1 0 | 0 1 1 0 | 06
; 3 0 0 1 1 | 1 0 1 0 | 0A
; 4 1 0 0 1 | 1 0 0 1 | 09
; entspricht: .dw 0x0605,0x090A
;
; Timer TC0:
; Timer laeuft bei einem Prozessortakt von 1,2 MHz mit
; einem Vorteiler von 1024 im CTC-Modus mit CompareA
; als TOP-Wert. Interrupt bei CompareA bzw. beim
; CTC-Reset.
; Bei CompareA wird der Soll- und Ist-Wert des
; Schrittmotors verglichen. Ist der Ist-Wert zu
; hoch, wird ein Schritt zurueck gefahren, ist
; der Ist-Wert zu niedrig, wird ein Schritt vor-
; waerts gefahren. Stimmen Soll- und Ist-Wert
; ueberein, werden nach einer einstellbaren Verzoe-
; gerung die Magnete des Schrittmotor abgeschaltet
; Timing: 1,2 MHz / 1024 / CompA,
; bei CompA = 255: f(Schrittmotor) = 4,57 Hz
; bei CompA = 8 : f(Schrittmotor) = 146 Hz
; ADC:
; Umwandlung der an Pin 3 / PB4 /ADC2 anliegenden
; Analogspannung, Aufsummieren von 64 Messungen
; zur Mittelung, Umrechnung in die Sollstellung
; des Schrittmotors
; Timing: 1,2 MHz / 128 = 9,375 kHz = 106,7 us
; Conversion = 13 cycles = 1,387 ms / Konversion
; = 721 Konversionen pro Sekunde
; Mittelung ueber 64 Konversionen = 88,75 ms = 11,3 / s
;
; Konstanten
;
.equ cSmSteps = 1276 ; 2552/2, Anzahl Schritte pro Umdrehung
.equ cSmFreq = 145 ; Frequenz Schrittmotorgeschwindigkeit
; ; Minimum: 5 Hz, Maximum: 1171 Hz
.equ cSmDelay = 390 ; Anzahl Takte vor Abschalten der Magnete
;
; Abgeleitete Konstanten
;
.equ clock = 1200000 ; Taktfrequenz Tiny13
.equ Tc0Ctc = 1024 ; Vorteiler TC0
.equ cCmpA = clock / 1024 / cSmFreq
;
; Ueberpruefung der Konstanten
;
.IF cCmpA > 255
.ERROR "Schrittmotor zu langsam!"
.ENDIF
.IF cCmpA < 1
.ERROR "Schrittmotor zu schnell!"
.ENDIF
;
; SRAM
;
; Register
;
; benutzt: R0 fuer Tabellenlesen
; benutzt: R8:R1 fuer Rechnen
; frei: R10:R8
.def rAdcCL = R11 ; ADC Rechenwert LSB
.def rAdcCH = R12 ; dto., MSB
.def rAdcRL = R13 ; ADC Uebergabe LSB
.def rAdcRH = R14 ; dto., MSB
.def rSreg = R15 ; Status Sicherungs-Register
.def rmp = R16 ; Multipurpose outside Int
.def rimp = R17 ; Multipurpose inside Int
.def rFlg = R18 ; Flaggen
.equ bAdc = 0 ; Adc conversion complete flag
.def rAdcC = R19 ; ADC Zaehler (64 Adc-Werte)
.def rAdcL = R20 ; ADC Addier-Register LSB
.def rAdcH = R21 ; dto., MSB
.def rSmSL = R22 ; Stepmotor-Sollwert LSB
.def rSmSH = R23 ; dto., MSB
.def rSmIL = R24 ; Stepmotor-Istwert LSB
.def rSmIH = R25 ; dto., MSB
; benutzt: X fuer Nachlauf der Magnete
; frei: Y
; benutzt: Z fuer Tabellenwert-Zugriff
;
; **********************************
; Code Segment Start, Int - Vektor
; **********************************
;
.cseg
.org $0000
;
rjmp Main ; Reset Vektor
reti ; INT0 Vektor
reti ; PCINT0 Vektor
reti ; TIM0_OVF Vektor
reti ; EE_RDY Vektor
reti ; ANA_COMP Vektor
rjmp Tc0IntCA ; TIM0_COMPA Vektor
reti ; TIM0_COMPB Vektor
reti ; WDT Vektor
rjmp AdcInt ; ADC Vektor
;
; **********************************
; Interrupt Service Routinen
; **********************************
;
; Timer-Counter 0 Compare A Interrupt Service Routine
;
Tc0IntCA:
in rSreg,SREG ; rette Status
cp rSmIL,rSmSL ; vergleiche Ist mit Soll
cpc rSmIH,rSmSH
breq Tc0IntCA0
brcs Tc0IntCAF ; Ist < Soll
sbiw rSmIL,1 ; Ist > Soll, ein Schritt rueckwaerts
rjmp Tc0IntCAS
Tc0IntCAF:
adiw rSmIL,1 ; ein Schritt vorwaerts
Tc0IntCAS:
mov rimp,rSmIL ; kopiere Zaehlerstand
andi rimp,0x03 ; isoliere unterste zwei Bits
ldi ZH,HIGH(2*SmTab) ; Zeige auf Tabelle
ldi ZL,LOW(2*SmTab)
add ZL,rimp
ldi rimp,0
adc ZH,rimp
lpm ; lese Wert aus Tabelle
.IF debug_out == 0
out PORTB,R0 ; schreibe auf Port
.ENDIF
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
out SREG,rSreg ; Stelle Status wieder her
reti
Tc0IntCA0:
sbiw XL,1 ; Delay-Zaehler verringern
brne Tc0IntCAD ; noch nicht Null
ldi rimp,0 ; Magnete ausschalten
out PORTB,rimp ; an Ausgangstreiber
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
Tc0IntCAD:
out SREG,rSreg ; stelle Status wieder her
reti
;
SmTab:
.dw 0x0605,0x090A
;
; Adc Conversion Complete Interrupt Service Routine
;
AdcInt:
in rSreg,SREG ; rette Status
in rimp,ADCL ; lese LSB Ergebnis
add rAdcL,rimp ; addiere zum Ergebnis
in rimp,ADCH ; lese MSB Ergebnis
adc rAdcH,rimp ; addiere zum Ergebnis
dec rAdcC ; Erniedrige Zaehler
brne AdcInt1
mov rAdcRL,rAdcL ; Kopiere Ergebnis
mov rAdcRH,rAdcH
clr rAdcH ; Loesche Summe
clr rAdcL
ldi rAdcC,64 ; Setze Zaehler neu
sbr rFlg,1<<bAdc ; Setze Flagge
AdcInt1:
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
out SREG,rSreg ; stelle Status wieder her
reti
;
; **********************************
; Hauptprogramm Init und Loop
; **********************************
;
Main:
; Stack Init
ldi rmp, LOW(RAMEND)
out SPL,rmp
; Init Register
clr rFlg ; Flag-Register auf Null
clr rSmIL ; Ist-Zaehler Stepmotor auf Null
clr rSmIH
clr rSmSL ; Soll-Wert Stepmotor auf Null
clr rSmSH
ldi XH,HIGH(cSmDelay) ; Delay-Zaehler-Restart
ldi XL,LOW(cSmDelay)
; Init Output-Port
ldi rmp,0x0F ; Ausgabe auf Port 0 is 3
out DDRB,rmp
ldi rmp,0x05 ; Schrittmotor auf Schritt 1 setzen
out PORTB,rmp
; Debugging session
.IF debug_calc
.equ adc_result = 128
ldi rmp,HIGH(adc_result)
mov rAdcRH,rmp
ldi rmp,LOW(adc_result)
mov rAdcRL,rmp
rjmp dcalc
.ENDIF
.IF debug_const
.equ const = cMSteps
ldi rmp,HIGH(const)
mov rSmSH,rmp
ldi rmp,LOW(const)
mov rSmSL,rmp
.ENDIF
; Init ADC
ldi rAdcC,64 ; Setze Zaehler neu
clr rAdcL ; Setze Ergebnis auf Null
clr rAdcH
ldi rmp,1<<ADC2D ; Digital Input Disable
out DIDR0,rmp
ldi rmp,1<<MUX1 ; ADC auf Kanal 2
out ADMUX,rmp
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
; TC0 initiieren
ldi rmp,cCmpA ; CTC-Wert setzen
out OCR0A,rmp
ldi rmp,1<<WGM01 ; CTC-Mode
out TCCR0A,rmp
ldi rmp,(1<<CS02)|(1<<CS00) ; Prescaler = 1024
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Interrupt Compare Match A enable
out TIMSK0,rmp
; Sleep Mode und Int Enable
ldi rmp,1<<SE ; Schlafen Enable
out MCUCR,rmp
sei ; Int Enable
Loop:
sleep ; schlafen
nop ; Dummy fuer Aufwachen
sbrc rFlg,bAdc ; ADC-Flagge?
rcall AdcRdy ; wandle ADC-Ergebnis um
rjmp Loop
;
; **********************************
; Rechenroutinen
; **********************************
;
; ADC Umwandlungs-Egebnis fertig
;
AdcRdy:
cbr rFlg,1<<bAdc ; setze Flagge zurueck
.IF debug_const
ret
.ENDIF
dcalc:
mov rAdcCH,rAdcRH ; kopiere Messwert
mov rAdcCL,rAdcRL
ldi rmp,LOW(cSmSteps) ; Anzahl Schritte in R4:R3:R2:R1
mov R1,rmp
ldi rmp,HIGH(cSmSteps)
mov R2,rmp
clr R3
clr R4
clr R5 ; Ergebnis in R8:R7:R6:R5 loeschen
clr R6
clr R7
clr R8
AdcRdy1:
lsr rAdcCH ; ein Bit herausschieben
ror rAdcCL
brcc AdcRdy2 ; nicht addieren
add R5,R1 ; addieren
adc R6,R2
adc R7,R3
adc R8,R4
AdcRdy2:
lsl R1 ; Multiplikator mal zwei
rol R2
rol R3
rol R4
mov rmp,rAdcCL ; = Null?
or rmp,rAdcCH
brne AdcRdy1 ; weiter multiplizieren
ldi rmp,0x80 ; aufrunden
add R5,rmp
adc R6,rmp
ldi rmp,0
adc R7,rmp
adc R8,rmp
cli ; Interrupts aus
mov rSmSL,R7 ; Stepmotor-Sollwert LSB
mov rSmSH,R8 ; dto., setze MSB
.IF debug_out
out PORTB,rSmSL
.ENDIF
sei ; Interrupts wieder an
ret
;
; Ende Source Code
;

http://www.avr-asm-tutorial.net/avr_de/quellen/schrittmotor_v1.asm1/20/2009 7:41:45 PM
http://www.avr-asm-tutorial.net/avr_de/rechteckgen/bilder/rechteckgen_scheme_v1_m8.gif

http://www.avr-asm-tutorial.net/avr_de/rechteckgen/bilder/rechteckgen_scheme_v1_m8.gif1/20/2009 7:41:47 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/scheme.gif

http://www.avr-asm-tutorial.net/avr_de/fcount/scheme.gif1/20/2009 7:41:52 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/analog3.gif

http://www.avr-asm-tutorial.net/avr_de/fcount/analog3.gif1/20/2009 7:41:53 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/FusesStudio1.gif

http://www.avr-asm-tutorial.net/avr_de/fcount/FusesStudio1.gif1/20/2009 7:41:55 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/FusesPony.gif

http://www.avr-asm-tutorial.net/avr_de/fcount/FusesPony.gif1/20/2009 7:42:19 PM
http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr_600_725.gif

http://www.avr-asm-tutorial.net/avr_de/eieruhr/eieruhr_600_725.gif1/20/2009 7:42:22 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/stepper_v1.gif

http://www.avr-asm-tutorial.net/avr_de/stepper/stepper_v1.gif1/20/2009 7:42:25 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/driver.jpg

http://www.avr-asm-tutorial.net/avr_de/stepper/driver.jpg1/20/2009 7:42:27 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/supply.gif

http://www.avr-asm-tutorial.net/avr_de/stepper/supply.gif1/20/2009 7:42:29 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/supply.jpg

http://www.avr-asm-tutorial.net/avr_de/stepper/supply.jpg1/20/2009 7:42:32 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/kp4m4-001.jpg

http://www.avr-asm-tutorial.net/avr_de/stepper/kp4m4-001.jpg1/20/2009 7:42:34 PM
http://www.avr-asm-tutorial.net/avr_de/stepper/stepper_sm.jpg

http://www.avr-asm-tutorial.net/avr_de/stepper/stepper_sm.jpg1/20/2009 7:42:36 PM
Anschluss einer LCD-Anzeige an das STK500

Pfad: Home => AVR-Übersicht => 4-Bit-LCD am STK500

Anschluss einer 2-zeiligen LCD-Anzeige an das


STK500
Beim Entwicklerboard STK500 ist keine LCD-Schnittstelle dabei, über die eine handelsübliche
Anzeige angeschlossen werden kann. Eine solche war beim STK200 mit dabei, aber auch die hat ihre
Macken: Sie lässt sich nicht zusammen mit externem SRAM betreiben (wegen memory mapping der
Anzeigeschnittstelle). Man kann aber eine LCD-Anzeige auch an jeden AVR-Port anschließen, an
dem man 6 Portbits noch frei und verfügbar hat. Die Anzeige wird dabei im 4-Bit-Modus angesteuert,
damit man Portbits sparen kann. Nimmt man ferner in Kauf, dass man aus der LCD nichts auslesen
kann (z.B. den Status oder den Zeichengenerator), dann kann man die Hard- und Software einfach
gestalten. Der Nachteil ist, dass man das Schreib-Timing über Verzögerungsschleifen durchführen
muss. Aber das ist nicht sooo schlimm.

Hardware
Die Hardware ist im folgenden Bild beschrieben.

Es kommt also nur darauf an,


das richtige

● Port-Bit mit dem richtigen


LCD-Pin,
● Stromversorgungspin mit

dem an der LCD, und das


richtige
● Poti mit dem

Helligkeitsregler-Eingang der
LCD (nein, es geht nicht ohne
das Poti!)

zu verbinden und schon ist die


Hardware gelaufen. Fast! Steht
das Poti falsch, sieht man nix.
Ohne Prozessoransteuerung
sollten beim Drehen am Poti
schwarze Kästchen sichtbar
werden. Den Kontrastregler
soweit drehen, dass die
Kästchen gerade nicht mehr zu
erkennen sind.

Software
Die Software zur Ansteuerung der LCD wird in der Datei Lcd4Inc im HTML-Format und in der
Datei Lcd4Inc im Quelltext-Format zur Verfügung gestellt. Sie besteht aus den Routinen

1. Lcd4Init: Die Routine setzt die LCD zurück,


2. Lcd4Chr: Sie gibt den Buchstaben in rmp auf der LCD aus,
3. Lcd4PBcd: Sie gibt die gepackte BCD-Zahl in rmp auf der LCD aus,
4. Lcd4ZTxt: Sie gibt den nullterminierten Text aus dem Flash ab Z aus,
5. Lcd4RTxt: Sie gibt rmp Buchstaben aus dem SRAM ab Z aus.

Die Software kann als Include-Datei in ein bestehendes Programm eingebunden werden. Im Kopf der
Datei sind die Bedingungen angegeben, die die Quelldatei einhalten muss.

Testprogramm
Als kleines Testprogramm ist eine Uhr programmiert, die die LCD-Anzeige zur Ausgabe der Uhrzeit
und des Datums verwendet. Diese Software ist in der Datei LcdIncC.html im HTML-Format und in
der Datei Lcd4IncC.asm im Quelltext-Format enthalten. Leider kann man die Uhr nicht verstellen.
Wer möchte kann sich Taster zum Verstellen und ein SIO-Interface für den PC dazuschreiben.

©2002-2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/lcd4_500.html1/20/2009 7:42:41 PM
Anschluss einer LCD-Anzeige an das STK500

Pfad: Home => AVR-Übersicht => Board-Hardware => 4-Bit-LCD am STK500 => Quellcode
Basisroutinen

; ********************************************
; * LCD-Basisroutinen für 4-Bit-Anschluss *
; * einer zweizeiligen LCD an einen ATMEL- *
; * Port, Bits 4..7=Data, Bit 1=RS, Bit0=E *
; * Version 1, Februar 2002, (C) 2002 by *
; * Gerhard Schmidt, bug reports and sug- *
; * gestions to info!at!avr-asm-tutorial.net *
; ********************************************
;
; Hardware: LCD-Anzeige am aktiven Port
;
; Definitionen, die in dem aufrufenden Assembler-
; Programm enthalten sein müssen:
; - Stackoperationen
; - Register rmp (R16..R31)
; - Taktfrequenz ftakt
; - pLcdPort Aktiver LCD-Port
; - pLcdDdr Datenrichtungsregister des aktiven Port
; Subroutinen:
; - Lcd4Init: Setzt die LCD zurück
; - Lcd4Chr: Gibt den Character in rmp aus
; - Lcd4PBcd: Gibt die gepackte BCD-Zahl in rmp aus
; - Lcd4ZTxt: Gib nullterminierten Text aus Flash ab Z
; - Lcd4RTxt: Gib rmp chars aus SRAM ab Z aus
;
; Festlegungen für den LCD-Port
.EQU cLcdWrite=0b11111111 ; Datenrichtung Schreibe LCD
.EQU cLcdDummy=0b00111000 ; Dummy-Function-Word
.EQU mLcdRs=0b00000010 ; RS-Bit Maske
.EQU bLcdEn=0 ; Enable Bit
.EQU c1s=200 ; Warten zu Beginn (200 * 5 ms)
.EQU c5ms=ftakt/800 ; 5 ms Warten nach jedem Kontrollwort
.EQU c50us=ftakt/80000 ; 50 us Warten nach jedem Zeichen
;
; Makro für Enable active time
;
; Version für 10 MHz Takt
;.MACRO enactive
; nop
; nop
; nop
; nop
; nop
;.ENDMACRO
;
; Version für 4 MHz Takt
;
.MACRO enactive
nop
nop
.ENDMACRO
;
Lcd4Init:
rcall LcdDelay1s ; Warte eine Sekunde auf LCD
ldi rmp,cLcdWrite ; Datenrichtung auf Ausgang
out pLcdDdr,rmp
ldi rmp,cLcdDummy ; Dummy zum Abfangen der LCD
rcall Lcd4Set ; drei Mal senden mit Delay je 5 ms
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,0b00101000 ; Function Set auf 4 Bit
rcall Lcd4Ctrl ; Ausgabe auf Control Port LCD
ldi rmp,0b00010100 ; Cursor display shift
rcall Lcd4Ctrl
ldi rmp,0b00001100 ; LCD on
rcall Lcd4Ctrl
ldi rmp,0b00000110 ; Entry mode
rcall Lcd4Ctrl
Lcd4Clear:
ldi rmp,0b00000001 ; Set Lcd Clear
rcall Lcd4Ctrl
Lcd4Home:
ldi rmp,0b00000010 ; Set LCD Home Position
;
; Ausgabe von rmp an den Control-Port der LCD
;
Lcd4Ctrl:
push rmp ; Rette Byte
andi rmp,0xF0 ; Lösche unteres Nibble
rcall Lcd4Set ; Gib oberes Nibble aus
pop rmp ; Stelle Byte wieder her
swap rmp ; Vertausche Nibbles
andi rmp,0xF0 ; Lösche unteres Nibble
rcall Lcd4Set ; Gib unteres Nibble aus
rjmp LcdDelay5ms ; Fertig
;
; Gib die gepackte BCD-Zahl in rmp auf dem LCD aus
;
Lcd4PBcd:
push rmp ; Save on stack
swap rmp ; Higher to lower nibble
rcall Lcd4PBcd1 ; Output nibble
pop rmp ; Restore from stack
Lcd4PBcd1:
andi rmp,0x0F ; Mask upper nibble
ori rmp,0x30 ; Nibble to ASCII
;
; Gib char in rmp auf LCD aus
;
Lcd4Chr:
push rmp ; Rette char auf Stapel
andi rmp,0xF0 ; Lösche unteres Nibble
sbr rmp,mLcdRs ; Setze RS-Bit
rcall Lcd4Set ; Gib Nibble aus
pop rmp ; Hole Char vom Stapel
swap rmp ; Vertausche Nibble
andi rmp,0xF0 ; Lösche unteres Nibble
sbr rmp,mLcdRs ; Setze RS-Bit
rcall Lcd4Set ; Gib Nibble aus
rjmp LcdDelay50us ; Fertig
;
; Gib Nibble in rmp an LCD aus
;
Lcd4Set:
out pLcdPort,rmp ; Byte auf Ausgabeport
nop
sbi pLcdPort,bLcdEn ; Setze Enable-Bit
enactive ; Delay macro
cbi pLcdPort,bLcdEn ; Enable Bit löschen
nop
ret
;
; Verzögerung um 1 Sekunde bei Init der LCD
;
LcdDelay1s:
ldi rmp,c1s ; 200 * 5 ms warten
LcdDelay1s1:
rcall LcdDelay5ms
dec rmp
brne LcdDelay1s1
ret
;
; Verzögerung um 5 ms nach jedem Control Word
;
LcdDelay5ms:
push ZH
push ZL
ldi ZH,HIGH(c5ms)
ldi ZL,LOW(c5ms)
LcdDelay5ms1:
sbiw ZL,1
brne LcdDelay5ms1
pop ZL
pop ZH
ret
;
; Delay um 50 Mikrosekunden nach jedem Char
;
LcdDelay50us:
ldi rmp,c50us
LcdDelay50us1:
nop
dec rmp
brne LcdDelay50us1
ret
;
; Gib an der Position in rmp den Text ab Z aus (null-term.)
;
Lcd4ZTxt:
sbr rmp,0b10000000 ; Setze DD-RAM-Adresse
rcall Lcd4Ctrl
Lcd4ZTxt1:
lpm ; Get a char
tst R0 ; Null-Char?
breq Lcd4ZTxtR
mov rmp,R0
rcall Lcd4Chr
adiw ZL,1
rjmp Lcd4ZTxt1
Lcd4ZTxtR:
ret
;
; Gib rmp chars Text im SRAM ab Z aus
;
Lcd4RTxt:
mov R0,rmp ; R0 ist Zähler
Lcd4RTxt1:
ld rmp,Z+ ; Lese char
rcall Lcd4Chr
dec R0
brne Lcd4RTxt1
ret

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/Lcd4Inc.html1/20/2009 7:42:43 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/Lcd4Inc.asm

; *****************************************
; * LCD-Basisroutinen für 4-Bit-Anschluss *
; * einer zweizeiligen LCD an einen ATMEL-*
; * Port, Bits 4..7=Data, Bit 1=RS, Bit0=E*
; * Version 1, Februar 2002, (C) 2002 by *
; * Gerhard Schmidt, bug reports and sug- *
; * gestions to info@avr-asm-tutorial.net *
; *****************************************
;
; Hardware: LCD-Anzeige am aktiven Port
;
; Definitionen, die in dem aufrufenden Assembler-
; Programm enthalten sein müssen:
; - Stackoperationen
; - Register rmp (R16..R31)
; - Taktfrequenz ftakt
; - pLcdPort Aktiver LCD-Port
; - pLcdDdr Datenrichtungsregister des aktiven Port
; Subroutinen:
; - Lcd4Init: Setzt die LCD zurück
; - Lcd4Chr: Gibt den Character in rmp aus
; - Lcd4PBcd: Gibt die gepackte BCD-Zahl in rmp aus
; - Lcd4ZTxt: Gib nullterminierten Text aus Flash ab Z
; - Lcd4RTxt: Gib rmp chars aus SRAM ab Z aus
;
; Festlegungen für den LCD-Port
.EQU cLcdWrite=0b11111111 ; Datenrichtung Schreibe LCD
.EQU cLcdDummy=0b00111000 ; Dummy-Function-Word
.EQU mLcdRs=0b00000010 ; RS-Bit Maske
.EQU bLcdEn=0 ; Enable Bit
.EQU c1s=200 ; Warten zu Beginn (200 * 5 ms)
.EQU c5ms=ftakt/800 ; 5 ms Warten nach jedem Kontrollwort
.EQU c50us=ftakt/80000 ; 50 us Warten nach jedem Zeichen
;
; Makro für Enable active time
;
; Version für 10 MHz Takt
;.MACRO enactive
; nop
; nop
; nop
; nop
; nop
;.ENDMACRO
;
; Version für 4 MHz Takt
;
.MACRO enactive
nop
nop
.ENDMACRO
;
Lcd4Init:
rcall LcdDelay1s ; Warte eine Sekunde auf LCD
ldi rmp,cLcdWrite ; Datenrichtung auf Ausgang
out pLcdDdr,rmp
ldi rmp,cLcdDummy ; Dummy zum Abfangen der LCD
rcall Lcd4Set ; drei Mal senden mit Delay je 5 ms
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,0b00101000 ; Function Set auf 4 Bit
rcall Lcd4Ctrl ; Ausgabe auf Control Port LCD
ldi rmp,0b00010100 ; Cursor display shift
rcall Lcd4Ctrl
ldi rmp,0b00001100 ; LCD on
rcall Lcd4Ctrl
ldi rmp,0b00000110 ; Entry mode
rcall Lcd4Ctrl
Lcd4Clear:
ldi rmp,0b00000001 ; Set Lcd Clear
rcall Lcd4Ctrl
Lcd4Home:
ldi rmp,0b00000010 ; Set LCD Home Position
;
; Ausgabe von rmp an den Control-Port der LCD
;
Lcd4Ctrl:
push rmp ; Rette Byte
andi rmp,0xF0 ; Lösche unteres Nibble
rcall Lcd4Set ; Gib oberes Nibble aus
pop rmp ; Stelle Byte wieder her
swap rmp ; Vertausche Nibbles
andi rmp,0xF0 ; Lösche unteres Nibble
rcall Lcd4Set ; Gib unteres Nibble aus
rjmp LcdDelay5ms ; Fertig
;
; Gib die gepackte BCD-Zahl in rmp auf dem LCD aus
;
Lcd4PBcd:
push rmp ; Save on stack
swap rmp ; Higher to lower nibble
rcall Lcd4PBcd1 ; Output nibble
pop rmp ; Restore from stack
Lcd4PBcd1:
andi rmp,0x0F ; Mask upper nibble
ori rmp,0x30 ; Nibble to ASCII
;
; Gib char in rmp auf LCD aus
;
Lcd4Chr:
push rmp ; Rette char auf Stapel
andi rmp,0xF0 ; Lösche unteres Nibble
sbr rmp,mLcdRs ; Setze RS-Bit
rcall Lcd4Set ; Gib Nibble aus
pop rmp ; Hole Char vom Stapel
swap rmp ; Vertausche Nibble
andi rmp,0xF0 ; Lösche unteres Nibble
sbr rmp,mLcdRs ; Setze RS-Bit
rcall Lcd4Set ; Gib Nibble aus
rjmp LcdDelay50us ; Fertig
;
; Gib Nibble in rmp an LCD aus
;
Lcd4Set:
out pLcdPort,rmp ; Byte auf Ausgabeport
nop
sbi pLcdPort,bLcdEn ; Setze Enable-Bit
enactive ; Delay macro
cbi pLcdPort,bLcdEn ; Enable Bit löschen
nop
ret
;
; Verzögerung um 1 Sekunde bei Init der LCD
;
LcdDelay1s:
ldi rmp,c1s ; 200 * 5 ms warten
LcdDelay1s1:
rcall LcdDelay5ms
dec rmp
brne LcdDelay1s1
ret
;
; Verzögerung um 5 ms nach jedem Control Word
;
LcdDelay5ms:
push ZH
push ZL
ldi ZH,HIGH(c5ms)
ldi ZL,LOW(c5ms)
LcdDelay5ms1:
sbiw ZL,1
brne LcdDelay5ms1
pop ZL
pop ZH
ret
;
; Delay um 50 Mikrosekunden nach jedem Char
;
LcdDelay50us:
ldi rmp,c50us
LcdDelay50us1:
nop
dec rmp
brne LcdDelay50us1
ret
;
; Gib an der Position in rmp den Text ab Z aus (null-term.)
;
Lcd4ZTxt:
sbr rmp,0b10000000 ; Setze DD-RAM-Adresse
rcall Lcd4Ctrl
Lcd4ZTxt1:
lpm ; Get a char
tst R0 ; Null-Char?
breq Lcd4ZTxtR
mov rmp,R0
rcall Lcd4Chr
adiw ZL,1
rjmp Lcd4ZTxt1
Lcd4ZTxtR:
ret
;
; Gib rmp chars Text im SRAM ab Z aus
;
Lcd4RTxt:
mov R0,rmp ; R0 ist Zähler
Lcd4RTxt1:
ld rmp,Z+ ; Lese char
rcall Lcd4Chr
dec R0
brne Lcd4RTxt1
ret

http://www.avr-asm-tutorial.net/avr_de/quellen/Lcd4Inc.asm1/20/2009 7:42:45 PM
Anschluss einer LCD-Anzeige an das STK500

Pfad: Home => AVR-Übersicht => 4-Bit-LCD am STK500 => Quellcode Uhr

; ***************************************************************
; * Uhr mit 2-Zeilen-LCD-Anzeige für STK500 mit Timer/Counter 1 *
; * Anschluss der LCD über 4-Bit-Kabel an Port des STK500 *
; * Bit0=E, Bit1=RS, Bit4..7:D4..D7 *
; * Benötigt die LCD-Basisroutinen Lcd4Inc.asm *
; * Eingestellt auf Taktfrequenz 3,685 MHz des STK500 *
; * (C)2002 by info!at!avr-asm-tutorial.net *
; * Erstellt: 16.2.2002, Letzte Änderung: 17.2.2002 *
; ***************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Timing-Schema zur Erzeugung des 1-Sekunden-Taktes
;
;3.685.000Hz--> 460.625Hz --> 67 Hz --> 1 Hz
;
;+---------+ +----------+ +----------+ +--------+
;|CPU-Takt | |TC1-Teiler| |TC1-Compa-| |Register|
;|3,685 MHz|-->|Prescaler |-->|re Match A|-->| rdiv1s |--> 1 s
;|7,37MHz/2| |Teiler /8 | | /6875 | | /67 |
;+---------+ +----------+ +----------+ +--------+
;
; Konstanten
;
.EQU ftakt = 3685000 ; Frequenz STK500 interner Takt
.EQU cdivtc1 = 6875 ; Teiler für TC1
.EQU cdiv1s = 67 ; Teiler für 1 s
;
; Aktive Ports für LCD-Ausgabe
;
.EQU pLcdPort=PORTA ; LCD an PORT A angeschlossen
.EQU pLcdDdr=DDRA ; Datenrichtungsregister LCD-Port
;
; Benutzte Register
;
.DEF rint= R15 ; Interrupt temp register
.DEF rmp = R16 ; Multi-Purpose Register
.DEF rdiv1s = R17 ; Teiler durch 67
;
; Datensegment
;
; SRAM-Speicher für Datum und Uhrzeit
;
; Packed BCD: Z=Bit7..4, E=Bit3..0
;
; $0060 +1 +2 +3 +4 +5
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
; | Tag | |Monat| | Jahr| |Stund| |Minut| |Sekun|
; | Z E | | Z E | | Z E | | Z E | | Z E | | Z E |
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
;
.DSEG
.ORG $0060 ; Datensegment beginnt bei $0060
ramdt:
.BYTE 6 ; dd mm yy hh mm ss, packed BCD reservieren
;
; Code beginnt hier
;
.CSEG
.ORG $0000
;
; Reset- und Interrupt-Vektoren
;
rjmp Start ; Reset-vector
reti ; External Interrupt Request 0
reti ; External Interrupt Request 1
reti ; Timer/Counter1 Capture event
rjmp TCmp1A ; Timer/Counter1 Compare match A
reti ; Timer/Counter1 Compare match B
reti ; Timer/Counter1 Overflow
reti ; Timer/Counter0 Overflow
reti ; SPI Serial Transfer complete
reti ; Uart Rx char available
reti ; Uart Tx data register empty
reti ; Uart Tx complete
reti ; Analog comparator
;
; ************** Interrupt service routines ********
;
;
; Timer/Counter 1, Compare match A interrupt
;
TCmp1A:
in rint,SREG ; Status-Register retten
inc rdiv1s ; Teiler durch 67 erhöhen
out SREG,rint ; Status vor Int wieder herstellen
reti
;
; **************** Ende der Interrupt Service Routinen *********
;
; **************** Verschiedene Unterprogramme *************
;
; LCD-4-Bit-Routinen einbinden
;
.NOLIST
.INCLUDE "Lcd4IncE.asm"
.LIST
;
; Init date-time default
;
initdt:
ldi ZH,HIGH(2*initdtt) ; Set date/time to default
ldi ZL,LOW(2*initdtt)
ldi XH,HIGH(ramdt)
ldi XL,LOW(ramdt)
ldi rmp,6
initdt1:
lpm
st X+,R0
adiw ZL,1
dec rmp
brne initdt1
ret
initdtt: ; Default date and time table
.DB 0x17,0x02,0x02,0x14,0x05,0x00
;
; Add 1 to BCD number that Z points to
; R0 must be 0x06, R1 is used temporarily, R2 is restart
; value, rmp is maximum value for overflow
; return with carry set if no overflow occurs
;
inct:
ld R1,Z ; Read Packed BCD to R1
sec ; Set carry
adc R1,R0 ; add 06 and carry
brhs inct1 ; If half carry: don't sub 06
sub R1,R0 ; no half carry
inct1:
cp R1,rmp ; max value reached?
brcs inct2 ; no overflow
mov R1,R2 ; set to restart value
inct2:
st Z,R1 ; Write to RAM
ret ; and return
;
; Display date on LCD
;
dispdate:
clr rmp ; Set LCD home position
ldi ZH,HIGH(2*datet) ; display Date-Text
ldi ZL,LOW(2*datet)
rcall Lcd4ZTxt ; Gib nullterminierten Text aus
ldi rmp,'.' ; Separator für Datum
mov R0,rmp
ldi ZH,HIGH(ramdt) ; Zeige auf Datum
ldi ZL,LOW(ramdt)
rcall disp3 ; Gib drei PBCD-Zahlen mit Separator aus
;
; Display time on LCD
;
disptime:
ldi rmp,0x40 ; LCD Cursor Beginn 2. Zeile
ldi ZH,HIGH(2*timet) ; Display Time-Text
ldi ZL,LOW(2*timet)
rcall Lcd4ZTxt ; Gib nullterminierten String aus
ldi rmp,':' ; Separator für Zeit
mov R0,rmp
ldi ZH,HIGH(ramdt+3) ; Zeige auf Zeit
ldi ZL,LOW(ramdt+3)
rcall disp3 ; Gib die nächsten drei PBCD aus
lds rmp,ramdt+5 ; Lese Sekunden
com rmp ; Invertiere
out PORTB,rmp ; und gib auf LEDs aus
ret ; Fertig
;
; Text, nullterminiert, für Datum und Zeit auf LCD
;
datet:
.DB "Date: ",0x00,0x00
timet:
.DB "Time: ",0x00,0x00
;
; Gib die drei PBCD ab Z auf die LCD aus
; Separator (: oder .) in R0
;
disp3:
ld rmp,Z+ ; Lese Zahl
rcall Lcd4PBcd ; Gib Packed BCD aus
mov rmp,R0 ; Gib Separator aus
rcall Lcd4Chr
ld rmp,Z+ ; Lese nächste Zahl
rcall Lcd4PBcd
mov rmp,R0 ; Gib Separator aus
rcall Lcd4Chr
ld rmp,Z ; Lese dritte Zahl
rjmp Lcd4PBcd
;
; **************** Ende der Unterprogramme *********************
;
; ******************** Hauptprogram ****************************
;
; Hauptprogramm beginnt hier
;
Start:
ldi rmp,HIGH(RAMEND) ; Initiate stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,0b00100000 ; Sleep Mode Idle
out MCUCR,rmp
ser rmp ; Port B auf Ausgang
out DDRB,rmp
rcall Lcd4Init ; Init LCD output
rcall initdt ; Init date and time default
rcall dispdate ; Default date/time to LCD
clr rmp
out TCNT1H,rmp ; High Byte TC1 clear
out TCNT1L,rmp ; Low Byte TC1 clear
ldi rmp,HIGH(cdivtc1) ; Compare Match, MSB first
out OCR1AH,rmp
ldi rmp,LOW(cdivtc1) ; Compare Match A, LSB last
out OCR1AL,rmp
ldi rmp,0b01000000 ; Toggle Output A on Comp Match
out TCCR1A,rmp
ldi rmp,0b00001010 ; Clear on Comp Match A, Div 8
out TCCR1B,rmp ; Start Timer
ldi rmp,0b01000000 ; TC1 CompA Int Enable
out TIMSK,rmp
sei
loop:
sleep ; Schlafenlegen
nop ; Aufwachen
cpi rdiv1s,cdiv1s ; 67 erreicht?
brcs loop ; not nicht
clr rdiv1s ; Neustart, Sekunde zu Ende
ldi rmp,0x06 ; Addiere Packed BCD Sekunden
mov R0,rmp ; Konstante wird für Packed BCD benötigt
clr R2 ; Startwert für Überlauf auf höherwertige Zahl
ldi rmp,0x60 ; Überlaufwert für Sekunden
ldi ZH,HIGH(ramdt+5) ; Auf SRAM-Adresse der Sekunden
ldi ZL,LOW(ramdt+5)
rcall inct ; inc seconds
brcs tok ; Time is ok
sbiw ZL,1 ; set pointer to minutes
rcall inct ; inc minutes
brcs tok ; time is ok
ldi rmp,0x24 ; maximum value for hours
sbiw ZL,1 ; Point to hours
rcall inct ; inc hours
brcs tok ; time is ok
inc R2 ; Set Day/Month default to 1
ldi ZH,HIGH(ramdt+1) ; Point to month
ldi ZL,LOW(ramdt+1)
ld rmp,Z ; Read month
cpi rmp,0x02 ; February?
brne nonfeb ; Not February
adiw ZL,1 ; Point to year
ld rmp,Z ; Read year
tst rmp ; Year=00?
breq m28 ; February 2000 is 28 days only
andi rmp,0x10 ; Tens of Years=odd?
ld rmp,Z ; Read year again
brne yodd ; Tens of years odd
andi rmp,0x03 ; lower nibble year=0,4,8?
brne m28 ; February has 28 days
m29:
ldi rmp,0x30 ; February has 29 days
rjmp mok ; month is ok
yodd:
andi rmp,0x03 ; Tens of years are odd
cpi rmp,0x02 ; Lower nibble year=2 or 6?
breq m29 ; Yes, February has 29 days
m28:
ldi rmp,0x29 ; February has 28 days
rjmp mok
nonfeb:
cpi rmp,0x07 ; Month > June?
brcs monthok ; No, don't inc
dec rmp ; back one month
monthok:
andi rmp,0x01 ; Odd month?
brne m31 ; Month has 31 days
ldi rmp,0x31 ; Month has 30 days
rjmp mok
m31:
ldi rmp,0x32 ; Month has 31 days
mok:
ldi ZH,HIGH(ramdt) ; Point to day
ldi ZL,LOW(ramdt)
rcall inct ; add 1 day
brcs dok ; Date is ok
adiw ZL,1 ; Point to month
ldi rmp,0x13 ; Max monthes
rcall inct ; next month
brcs dok ; Date is ok
adiw ZL,1 ; Point to year
clr R2 ; Default year=00
rcall inct ; Next year
;
; Refresh date on LCD
;
dok:
rcall dispdate ; Display date
;
; Refresh time on LCD
;
tok:
rcall disptime ; Display time
rjmp loop
;
; Ende des Programmes
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/Lcd4IncC.html1/20/2009 7:42:48 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/Lcd4IncC.asm

; ***************************************************************
; * Uhr mit 2-Zeilen-LCD-Anzeige für STK500 mit Timer/Counter 1 *
; * Anschluss der LCD über 4-Bit-Kabel an Port des STK500 *
; * Bit0=E, Bit1=RS, Bit4..7:D4..D7 *
; * Benötigt die LCD-Basisroutinen Lcd4Inc.asm *
; * Eingestellt auf Taktfrequenz 3,685 MHz des STK500 *
; * (C)2002 by info@avr-asm-tutorial.net *
; * Erstellt: 16.2.2002, Letzte Änderung: 17.2.2002 *
; ***************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Timing-Schema zur Erzeugung des 1-Sekunden-Taktes
;
;3.685.000Hz--> 460.625Hz --> 67 Hz --> 1 Hz
;
;+---------+ +----------+ +----------+ +--------+
;|CPU-Takt | |TC1-Teiler| |TC1-Compa-| |Register|
;|3,685 MHz|-->|Prescaler |-->|re Match A|-->| rdiv1s |--> 1 s
;|7,37MHz/2| |Teiler /8 | | /6875 | | /67 |
;+---------+ +----------+ +----------+ +--------+
;
; Konstanten
;
.EQU ftakt = 3685000 ; Frequenz STK500 interner Takt
.EQU cdivtc1 = 6875 ; Teiler für TC1
.EQU cdiv1s = 67 ; Teiler für 1 s
;
; Aktive Ports für LCD-Ausgabe
;
.EQU pLcdPort=PORTA ; LCD an PORT A angeschlossen
.EQU pLcdDdr=DDRA ; Datenrichtungsregister LCD-Port
;
; Benutzte Register
;
.DEF rint= R15 ; Interrupt temp register
.DEF rmp = R16 ; Multi-Purpose Register
.DEF rdiv1s = R17 ; Teiler durch 67
;
; Datensegment
;
; SRAM-Speicher für Datum und Uhrzeit
;
; Packed BCD: Z=Bit7..4, E=Bit3..0
;
; $0060 +1 +2 +3 +4 +5
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
; | Tag | |Monat| | Jahr| |Stund| |Minut| |Sekun|
;|ZE||ZE||ZE||ZE||ZE||ZE|
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
;
.DSEG
.ORG $0060 ; Datensegment beginnt bei $0060
ramdt:
.BYTE 6 ; dd mm yy hh mm ss, packed BCD reservieren
;
; Code beginnt hier
;
.CSEG
.ORG $0000
;
; Reset- und Interrupt-Vektoren
;
rjmp Start ; Reset-vector
reti ; External Interrupt Request 0
reti ; External Interrupt Request 1
reti ; Timer/Counter1 Capture event
rjmp TCmp1A ; Timer/Counter1 Compare match A
reti ; Timer/Counter1 Compare match B
reti ; Timer/Counter1 Overflow
reti ; Timer/Counter0 Overflow
reti ; SPI Serial Transfer complete
reti ; Uart Rx char available
reti ; Uart Tx data register empty
reti ; Uart Tx complete
reti ; Analog comparator
;
; ************** Interrupt service routines ********
;
;
; Timer/Counter 1, Compare match A interrupt
;
TCmp1A:
in rint,SREG ; Status-Register retten
inc rdiv1s ; Teiler durch 67 erhöhen
out SREG,rint ; Status vor Int wieder herstellen
reti
;
; **************** Ende der Interrupt Service Routinen *********
;
; **************** Verschiedene Unterprogramme *************
;
; LCD-4-Bit-Routinen einbinden
;
.NOLIST
.INCLUDE "Lcd4IncE.asm"
.LIST
;
; Init date-time default
;
initdt:
ldi ZH,HIGH(2*initdtt) ; Set date/time to default
ldi ZL,LOW(2*initdtt)
ldi XH,HIGH(ramdt)
ldi XL,LOW(ramdt)
ldi rmp,6
initdt1:
lpm
st X+,R0
adiw ZL,1
dec rmp
brne initdt1
ret
initdtt: ; Default date and time table
.DB 0x17,0x02,0x02,0x14,0x05,0x00
;
; Add 1 to BCD number that Z points to
; R0 must be 0x06, R1 is used temporarily, R2 is restart
; value, rmp is maximum value for overflow
; return with carry set if no overflow occurs
;
inct:
ld R1,Z ; Read Packed BCD to R1
sec ; Set carry
adc R1,R0 ; add 06 and carry
brhs inct1 ; If half carry: don't sub 06
sub R1,R0 ; no half carry
inct1:
cp R1,rmp ; max value reached?
brcs inct2 ; no overflow
mov R1,R2 ; set to restart value
inct2:
st Z,R1 ; Write to RAM
ret ; and return
;
; Display date on LCD
;
dispdate:
clr rmp ; Set LCD home position
ldi ZH,HIGH(2*datet) ; display Date-Text
ldi ZL,LOW(2*datet)
rcall Lcd4ZTxt ; Gib nullterminierten Text aus
ldi rmp,'.' ; Separator für Datum
mov R0,rmp
ldi ZH,HIGH(ramdt) ; Zeige auf Datum
ldi ZL,LOW(ramdt)
rcall disp3 ; Gib drei PBCD-Zahlen mit Separator aus
;
; Display time on LCD
;
disptime:
ldi rmp,0x40 ; LCD Cursor Beginn 2. Zeile
ldi ZH,HIGH(2*timet) ; Display Time-Text
ldi ZL,LOW(2*timet)
rcall Lcd4ZTxt ; Gib nullterminierten String aus
ldi rmp,':' ; Separator für Zeit
mov R0,rmp
ldi ZH,HIGH(ramdt+3) ; Zeige auf Zeit
ldi ZL,LOW(ramdt+3)
rcall disp3 ; Gib die nächsten drei PBCD aus
lds rmp,ramdt+5 ; Lese Sekunden
com rmp ; Invertiere
out PORTB,rmp ; und gib auf LEDs aus
ret ; Fertig
;
; Text, nullterminiert, für Datum und Zeit auf LCD
;
datet:
.DB "Date: ",0x00,0x00
timet:
.DB "Time: ",0x00,0x00
;
; Gib die drei PBCD ab Z auf die LCD aus
; Separator (: oder .) in R0
;
disp3:
ld rmp,Z+ ; Lese Zahl
rcall Lcd4PBcd ; Gib Packed BCD aus
mov rmp,R0 ; Gib Separator aus
rcall Lcd4Chr
ld rmp,Z+ ; Lese nächste Zahl
rcall Lcd4PBcd
mov rmp,R0 ; Gib Separator aus
rcall Lcd4Chr
ld rmp,Z ; Lese dritte Zahl
rjmp Lcd4PBcd
;
; **************** Ende der Unterprogramme *********************
;
; ******************** Hauptprogram ****************************
;
; Hauptprogramm beginnt hier
;
Start:
ldi rmp,HIGH(RAMEND) ; Initiate stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,0b00100000 ; Sleep Mode Idle
out MCUCR,rmp
ser rmp ; Port B auf Ausgang
out DDRB,rmp
rcall Lcd4Init ; Init LCD output
rcall initdt ; Init date and time default
rcall dispdate ; Default date/time to LCD
clr rmp
out TCNT1H,rmp ; High Byte TC1 clear
out TCNT1L,rmp ; Low Byte TC1 clear
ldi rmp,HIGH(cdivtc1) ; Compare Match, MSB first
out OCR1AH,rmp
ldi rmp,LOW(cdivtc1) ; Compare Match A, LSB last
out OCR1AL,rmp
ldi rmp,0b01000000 ; Toggle Output A on Comp Match
out TCCR1A,rmp
ldi rmp,0b00001010 ; Clear on Comp Match A, Div 8
out TCCR1B,rmp ; Start Timer
ldi rmp,0b01000000 ; TC1 CompA Int Enable
out TIMSK,rmp
sei
loop:
sleep ; Schlafenlegen
nop ; Aufwachen
cpi rdiv1s,cdiv1s ; 67 erreicht?
brcs loop ; not nicht
clr rdiv1s ; Neustart, Sekunde zu Ende
ldi rmp,0x06 ; Addiere Packed BCD Sekunden
mov R0,rmp ; Konstante wird für Packed BCD benötigt
clr R2 ; Startwert für Überlauf auf höherwertige Zahl
ldi rmp,0x60 ; Überlaufwert für Sekunden
ldi ZH,HIGH(ramdt+5) ; Auf SRAM-Adresse der Sekunden
ldi ZL,LOW(ramdt+5)
rcall inct ; inc seconds
brcs tok ; Time is ok
sbiw ZL,1 ; set pointer to minutes
rcall inct ; inc minutes
brcs tok ; time is ok
ldi rmp,0x24 ; maximum value for hours
sbiw ZL,1 ; Point to hours
rcall inct ; inc hours
brcs tok ; time is ok
inc R2 ; Set Day/Month default to 1
ldi ZH,HIGH(ramdt+1) ; Point to month
ldi ZL,LOW(ramdt+1)
ld rmp,Z ; Read month
cpi rmp,0x02 ; February?
brne nonfeb ; Not February
adiw ZL,1 ; Point to year
ld rmp,Z ; Read year
tst rmp ; Year=00?
breq m28 ; February 2000 is 28 days only
andi rmp,0x10 ; Tens of Years=odd?
ld rmp,Z ; Read year again
brne yodd ; Tens of years odd
andi rmp,0x03 ; lower nibble year=0,4,8?
brne m28 ; February has 28 days
m29:
ldi rmp,0x30 ; February has 29 days
rjmp mok ; month is ok
yodd:
andi rmp,0x03 ; Tens of years are odd
cpi rmp,0x02 ; Lower nibble year=2 or 6?
breq m29 ; Yes, February has 29 days
m28:
ldi rmp,0x29 ; February has 28 days
rjmp mok
nonfeb:
cpi rmp,0x07 ; Month > June?
brcs monthok ; No, don't inc
dec rmp ; back one month
monthok:
andi rmp,0x01 ; Odd month?
brne m31 ; Month has 31 days
ldi rmp,0x31 ; Month has 30 days
rjmp mok
m31:
ldi rmp,0x32 ; Month has 31 days
mok:
ldi ZH,HIGH(ramdt) ; Point to day
ldi ZL,LOW(ramdt)
rcall inct ; add 1 day
brcs dok ; Date is ok
adiw ZL,1 ; Point to month
ldi rmp,0x13 ; Max monthes
rcall inct ; next month
brcs dok ; Date is ok
adiw ZL,1 ; Point to year
clr R2 ; Default year=00
rcall inct ; Next year
;
; Refresh date on LCD
;
dok:
rcall dispdate ; Display date
;
; Refresh time on LCD
;
tok:
rcall disptime ; Display time
rjmp loop
;
; Ende des Programmes
;

http://www.avr-asm-tutorial.net/avr_de/quellen/Lcd4IncC.asm1/20/2009 7:42:50 PM
AVR-PWM-ADC-Test für STK500

Pfad: Home => AVR-Übersicht => PWM-ADC


Tutorial für das Erlernen der Assemblersprache von
AVR-Einchip-Prozessoren AT90Sxxxx
von ATMEL anhand geeigneter praktischer Beispiele.
Einfacher 8-Bit-Analog-Digital-Wandler mit PWM auf dem STK board

Aufgabe
Mit Hilfe der Analogeingänge AIN0 und AIN1 läßt sich ohne größeren zusätzlichen Aufwand an Hardware ein einfacher Analog-
Digital-Wandler erstellen. Der Analogvergleicher wird dabei benutzt, um eine mit dem Timer/Counter 1 (TC1) erzeugte
Vergleichsspannung mit der Eingangsspannung zu vergleichen und diese so lange nachzujustieren, bis das Ergebnis auf 8 Bit genau
feststeht. TC1 arbeitet dabei als Pulsweitenmodulator (PWM), das Tastverhältnis bestimmt die Ausgangsspannung.
Das Ergebnis der Wandlung wird auf den LEDs des STK500-Boards ausgegeben.

Erforderliche Hardware
Das Bild links zeigt die gesamte Testhardware zum Anschluss
an das STK500-Board. Die Portanschlüsse sind von oben
gezeichnet.
Die Messspannung von 0,00 bis 5,00 Volt wird mit dem 10k-
Poti aus der Betriebsspannung des Boards erzeugt und mit
einem Kondensator gefiltert. Sie wird an den Eingang des
Analogkomparators AIN0 (entspricht beim AT90S8515 dem
Port PB2) gelegt.
Die Vergleichsspannung wird aus dem PWM-Ausgang OC1A
(entspricht beim AT90S8515 dem Port PD5) erzeugt und über
drei RC-Filter mit 10k/100n an den analogen Vergleichseingang
AIN1 (entspricht beim AT90S8515 dem Port PB3) geführt. Das
ist schon alles.

Noch ein paar Hinweise zum Testaufbau am STK500. Das


RC-Filter und das Teststpannungspoti passen auf ein
kleines Lochplatinchen. Der Anschluss an das Board kann
mit den beim STK500 mitgelieferten zweipoligen
Anschlusskabeln vorgenommen werden, wenn man
entsprechende Pfostenstecker auf der Lochplatine vorsieht.
Nicht vergessen, dass die LEDs in dieser Schaltung leider
an Port C angeschlossen werden müssen, weil Port B für
die Analogeingänge gebraucht wird. Deshalb ist auch die
Schaltung und die Software für das STK200 nicht geeignet
(feste Verdrahtung der LEDs an Port B). Nach Abschluss
der Arbeiten nicht vergessen, die LEDs über das
Parallelkabel wieder an Port B anzuschließen, wo sie
standardmäßig hingehören.

An den Anfang dieser Seite

Funktionsweise

Erzeugung der Vergleichsspannung mit Pulsweitenmodulation

Ein Pulsweitenmodulator erzeugt ein Rechtecksignal mit einer festgelegten Pulsweite. Der Modulator erzeugt ein 1-Signal für eine
bestimmte Zeit lang, der Rest der Zeit ist der Ausgang auf Null. Filtert man diese Rechteckspannung, dann kann man über die
Pulsweite eine Analogspannung erzeugen. Stellt man ein Impuls-/Pausen- Verhältnis von 50% ein, dann ergibt sich am Ausgang des
Filters die halbe Betriebsspannung, entsprechend bei 25% ein Viertel, etc.
D

Lade- und Entladeverhältnisse an den RC-Filtern zeigt vereinfacht die Grafik. Die Rechteckspannung U(PWM) bildet sich noch
deutlich auf der Spannung am Kondensator C1 ab. Die Glättung am Kondensator C2 ist sehr deutlich zu erkennen. Allerdings ist das
Nachlaufen zu Beginn des Einschwingvorganges auch deutlich zu erkennen. Noch deutlicher ist dieses Nachlaufen am Kondensator
C3 zu sehen.
Weil sich auch im eingeschwungenen Zustand noch Lade- und Entladevorgänge auf das Ausgangssignal auswirken, muss das Filter
so dimensioniert sein, dass diese Restwelligkeit niedriger ist als das Auflösungsvermögen des AD-Wandlers. Bei 8 Bit Auflösung
und 5,0 Volt Betriebsspannung muss die Restwelligkeit deutlich unter 5/256 = 19,5 mV liegen. Vergrößerung der Widerstände und
Kondensatoren des RC-Filters oder das Hinzufügen weiterer RC-Glieder bewirkt eine Verminderung der Restwelligkeit.
Allerdings wird dadurch die Zeit, die der PWM-Modulator bis zum Einstellen der Analogspannung benötigt, ebenfalls länger. Daher
ist ein PWM-basierter ADC nicht sehr schnell (im vorliegenden Fall maximal etwa 5 Messungen pro Sekunde). In der Praxis wird
man einen Kompromiss zwischen Einschwingzeit und Restwelligkeit schließen. Die Einschwingzeit wird durch die Anzahl PWM-
Zyklen gewählt, die der AVR abwartet, bevor er den Analogvergleich am Port abliest. Sie ist daher durch Software einstellbar. Im
vorliegenden Fall wurden dafür 128 Zyklen gewählt, was für eine stabile Einschwingzeit bei der vorliegenden Dimensionierung
völlig ausreicht. Ohne Softwareänderung sind bis zu 65536 Zyklen möglich.
Für die Dimensionierung des RC wurde ein kleines Pascal-Programm entwickelt, das die Vorgänge beim PWM simuliert und die
Ermittlung der Restwelligkeit und Einschwingzeit ermöglicht. Es läuft auf der Kommandozeile. Der Quellcode avr_pwm1.pas kann
auf jedem gängigen Pascal-Compiler zu einem lauffähigen Programm kompiliert werden.
Die Frequenz, mit der der PWM arbeitet, ergibt sich bei 8-Bit-Auflösung zu

f (PWM) = Taktfrequenz / 510 (9 Bit: 1022, 10 Bit: 2046)

Bei einer Taktfrequenz von 3,685 MHz auf dem STK500 Board ergeben sich krumme 7.225,5 Hz PWM-Frequenz oder 138,4
Mikrosekunden pro PWM-Zyklus. Bei 128 Zyklen pro Bit ergeben sich Umwandlungszeiten von 142 Millisekunden pro Messung
oder 7 Messungen pro Sekunde. Nicht sehr schnell, aber immer noch schneller als das menschliche Auge.

Referenzspannung dieser Schaltung ist die Betriebsspannung des Prozessors. Diese kann eventuell mit dem Studio im STK500
verstellt werden. Die Genauigkeit des PWM-Signals ist im untersten Bereich (0,00 bis 0,10 V), aber mehr noch im oberen
Spannungsbereich nicht sehr genau, weil die MOS-Ausgangstreiber nicht ganz bis an die obere Betriebsspannung herankommen.
Das bedingt im mittleren Bereich zwar auch schon Ungenauigkeiten, wirkt sich aber in diesen Extrembereichen in Nichtlinearität
aus. Es hat deshalb auch keinen großen Sinn, 9 oder 10 Bits Auflösung anzustreben. Wer es genauer haben möchte, greift zu einem
Prozessor mit eingebauten AD-Wandlern.

An den Anfang dieser Seite

Methode der sukzessiven Approximation

Zum Messen der Eingangsspannung könnte man schrittweise die Pulsweite erhöhen und jeweils prüfen, ob die Spannung am
Vergleichseingang schon größer ist als die Eingangsspannung. Das erfordert bei 8 Bit Genauigkeit aber schon 255 Einzelschritte, bei
10 Bit Genauigkeit stolze 1023 Schritte.
Als Wandelmethode wird deshalb die sukzessive Approximation verwendet. Im ersten Schritt wird die Vergleichsspannung auf die
halbe Betriebsspannung eingestellt und festgestellt, ob die Messspannung darüber oder darunter liegt. Liegt sie darunter, wird die
Vergleichsspannung im nächsten Schritt auf ein Viertel eingestellt, liegt sie darüber, dann auf dreiviertel. Diese Schritte setzt man so
lange fort, bis man die Messspannung mit der nötigen Genauigkeit festgestellt hat. Bei 8 Bit Genauigkeit sind demnach acht
Schritte, bei 10 Bit zehn Schritte nötig. Das ist um den Faktor 30 (8 Bit) bzw. 100 schneller als die Methode mit der schrittweisen
Erhöhung der Vergleichsspannung.
Das Verfahren lässt sich leicht per Software umsetzen. Die ersten fünf Schritte sind für eine 8-Bit-Wandlung in der Tabelle
angegeben. Angegeben ist die Vergleichsspannung beim n-ten Schritt und die korrespondierende binäre Ausgabe an den 8-Bit-
PWM. Ist die Vergleichsspannung größer als die Messspannung, geht es beim oberen Kasten weiter. Umgekehrt beim unteren
Kasten.
1 2 3 4 5
1000.0000 0100.0000 0010.0000 0001.0000 0000.1000
U=0,15625V
U=0,3125V 0000.1000
0001.0000 U=0,46875V
U=0,625V 0001.1000
0010.0000 U=0,78125V
U=0,9375V 0010.1000
0011.0000 U=1,09375V
U=1,25V 0011.1000
0100.0000 U=1,40625V
U=1,5625V 0100.1000
0101.0000 U=1,71875V
U=1,875V 0101.1000
0110.0000 U=2,03125V
U=2,1875V 0110.1000
0111.0000 U=2,34375V
U=2,5V 0111.1000
1000.0000 U=2,65625V
U=2,8125V 1000.1000
1001.0000 U=2,96875V
U=3,125V 1001.1000
1010.0000 U=3,28125V
U=3,4375V 1010.1000
1011.0000 U=3,59375V
U=3,75V 1011.1000
1100.0000 U=3,90625V
U=4,0625V 1100.1000
1101.0000 U=4,21875V
U=4,375V 1101.1000
1110.0000 U=4,53125V
U=4,6875V 1110.1000
1111.0000 U=4,84375V
1111.1000
Das Muster ist leicht erkennbar: Zu Beginn jedes Schrittes ist das entsprechende Bit auf 1 zu setzen. Ist das zuviel an Spannung,
wird es beim nächsten Schritt wieder auf Null gesetzt. Ideal einfach zu programmieren!

Software
Die Software ist in HTML-Form als adc8.html und als ASM-Quellcode-Datei adc8.asm zugänglich.

Das Programm besteht aus sehr langen Wartezeiträmen, die der PWM braucht, bis sich die erzeugte Spannung stabilisiert hat. Das
ist ideal für den Einsatz von Interrupts, da wir sonst komplizierte und vom Timing her ausgeklügelte Verzögerungsschleifen
programmieren müssten. Weil der TC1 sowieso mit nichts anderem befasst ist als mit dem Hoch- und Runterzählen des PWM, kann
er das gesamte Timing der Messung mit übernehmen. Der Prozessor selbst ruht die meiste Zeit im Schlafmodus und wird alle 142
Mikrosekunden durch den PWM-Interrupt aufgeweckt. Nach der Feststellung, dass die Fertig- Flagge nicht gesetzt ist, kann er
weiter ruhen. Ist er fertig, muss das Ergebnis auf den Port und die Flagge wieder gelöscht werden.

An den Anfang dieser Seite

Hauptprogramm

Das Hauptprogramm durchläuft folgende Schritte:

1. Der Stapel wird eingerichtet. Das ist nötig, weil das Programm über Interrupts des Timers gesteuert abläuft. Interrupts
brauchen immer den Stapel, um die Rücksprungadresse dort ablegen zu können. Der Stapel wird auf dem obersten internen
SRAM angelegt.
2. Der Zyklenzähler wird gesetzt. Er bestimmt, nach wievielen Zyklen des PWM der Vergleich zwischen der erzeugten PWM-
Analogspannung mit dem analogen Eingangssignal erfolgt. Im Beispiel sind das 128 Zyklen. Es ist durch Ändern der
Konstanten CycLen0 einstellbar (z.B. um zu erreichen, dass jede Sekunde eine Messung beginnt).
3. Der Bitzähler rBlc wird zu Beginn auf 0x80 gesetzt. Das entspricht der halben Betriebsspannung als Vergleichsspannung.
Das Messergebnis in rTmp wird zu Beginn ebenfalls auf diesen Wert gesetzt.
4. Die Portausgänge von Port C zum Treiben der Leuchtdioden werden als Ausgänge geschaltet.
5. Das Portbit PD5 von Port D ist als Ausgang einzustellen, damit das PWM-Ausgangssignal außen am Portpin ausgegeben
werden kann.
6. Der Schlafmodus Idle muss eingestellt werden, damit die CPU auf die SLEEP-Instruction reagiert und beim Interrupt des
TC1 wieder korrekt aufwacht.
7. Timer/Counter 1 wird als 8-bit-PWM eingestellt und bezieht seinen Zähltakt direkt aus dem CPU-Takt (möglichst große
PWM-Frequenz).
8. Die PWM-Pulsweite wird auf 50% (0x0080) eingestellt.
9. Im Timer Int Mask Register wird der Overflow-Interrupt ermöglicht, damit TC1 nach jedem PWM-Zyklus einen Interrupt
auslöst.
10. Die Annahme von Interruptanforderungen durch die CPU wird ermöglicht.

Ab jetzt beginnt die Schleife, die nach jedem Aufwecken durch TC1 durchlaufen wird. Nachdem der Interrupt bearbeitet ist, wird
die Ready-Flagge befragt, ob der ADC-Vorgang schon durchlaufen und der gemessene Wert gültig ist. Ist das der Fall, wird die
Flagge wieder gelöscht, der gemessene Wert bitweise invertiert und an die Leuchtdioden ausgegeben. Dann versinkt die CPU wieder
in den Schlaf, bis ein neuer Messvorgang beendet ist und die Flagge nach dem Wecken gesetzt ist.

Interruptsteuerung

Zentrales Herzstück des AD-Wandlers ist der Pulsweitenmodulator mit dem Timer/Counter TC1. Immer wenn TC1 einen PWM-
Zyklus vollendet hat, wird der Overflow-Interrupt ausgelöst, der Programmzähler auf den Stapel abgelegt und der Programmablauf
zur Interruptroutine verzweigt. Diese Interruptroutine übernimmt selbstständig die gesamte PWM-ADC-Steuerung und teilt dem
Hauptprogramm über eine Flagge mit, wann die Umwandlung beendet und das Ergebnis gültig ist. Sie startet nach Ende einer
Messung automatisch wieder von vorne. Durch Einstellung der PWM-Zyklusanzahl zu Beginn einer Messung und der Anzahl PWM-
Zyklen für die Messung der Einzelbits ergibt sich die Wiederholzeit für die Messungen.
Im linken Bild ist der Algorithmus für die gesamte Steuerung des AD-
Wandlers abgebildet.
Es beginnt damit, dass der Inhalt des Statusregisters gesichert wird. Vor
der Rückkehr vom Interrupt wird dessen Originalinhalt wieder
hergestellt.
Im nächsten Schritt wird der Zähler für die PWM-Zyklen um Eins
erniedrigt und festgestellt, ob schon genügend PWM-Zyklen durchlaufen
sind, dass sich die vom PWM erzeugte und vom RC-Filter geglättete
Vergleichsspannung am Analog-Eingang AIN1 stabilisiert hat. Ist der
Zykluszähler noch nicht Null, werden weitere Zyklen abgewartet und
der Interrupt ist vorerst beendet.
Ist die vorgegebene Anzahl PWM-Zyklen durchlaufen, wird zunächst
der PWM-Zykluszähler auf seinen Voreinstellungswert gesetzt. Dann
wird der Analog-Komparator-Ausgang abgefragt, ob die
Vergleichsspannung an AIN1 größer oder kleiner als die zu messende
Spannung am Eingang AIN0 ist. War die Vergleichsspannung zu hoch,
wird das zuletzt gesetzte Bit wieder auf Null gesetzt. Wenn nicht, bleibt
es auf Eins.
Nun wird der Bitzähler mit dem aktiven Bit um eine Stelle nach rechts
geschoben. Dabei wird von links eine Null in Bit 7 des Bitzählers
hineingeschoben, nach rechts rutscht Bit 0 des Bitzählers in das Carry-
Flag des Statusregisters. Rollt dabei eine Null heraus, dann sind wir noch
nicht fertig und müssen uns weiter sukzessiv approximieren.
Rollt bei dem Vorgang eine Eins aus dem Bitzähler heraus, dann sind
wir fertig. Das Ergebnis im Temporärregister wird in das
Ergebnisregister kopiert, die Fertig-Flagge im Flaggenregister gesetzt,
der PWM-Zyklenzähler auf den längeren Anfangswert für den
Neuanfang gesetzt, das Temporärregister entleert und der Bitzähler auf
0x80 gesetzt (acht Näherungsschritte).
Schließlich wird das aktive Bit im Bitzähler auf das Temporärregister
übertragen (aktives Bit wird auf Eins gesetzt) und das Zwischenergebnis
dem PWM mitgeteilt, der damit die Vergleichsspannung am
Analogeingang AIN1 füttert.
Am Ende wird nur noch das Statusregister wieder in den Originalzustand
versetzt und vom Interrupt zurückgekehrt.

Die gesamte Interruptroutine ist mit maximal 25 Taktzyklen oder etwa 6 Mikrosekunden (bei 4 MHz) sehr kurz. Auch wenn noch
andere Tasks laufen, dürfte dies immer zu verkraften sein.

änderungen und Ergänzungen

Für Experimente mit 9- oder 10-Bit-Auflösung müssen die Register rRes, rTmp und rBlc als Zwei-Byte-Worte ausgeführt werden.
Bei der Ausgabe über die LEDs muss entschieden werden, welche Bits dargestellt oder nicht dargestellt werden sollen.
Soll das Ergebnis auf einer LCD-Anzeige angezeigt oder über die serielle Schnittstelle des Prozessors an einen Computer in
dezimaler Form ausgegeben werden, können die Festkomma-Umrechnungsroutinen in der Rechenabteilung des Anfängerkurses
hinzugebaut werden.

An den Anfang dieser Seite

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_adc500.html1/20/2009 7:43:02 PM
8-<A HREF="beginner/rechnen.html#Bits">Bit</A>-Analog-zu-Digital-Converter

Pfad: Home => AVR-Übersicht => 8-Bit-ADC am STK500 => adc8 software

Assembler Quelltext der Umwandlung einer


Analogspannung in eine 8-Bit-Zahl
; +-----------------------------------------------------+
; | 8-Bit-Analog-Digital-Converter mit ATMEL AT90S8515 |
; | auf dem STK500 board, Ausgabe über LEDs |
; | (C)2003 by http://www.avr-asm-tutorial.net |
; | Verwendete Anschlüsse: Ausgang PWM-Rechteckspannung |
; | OC1A an Port D, Bit 5; über dreifach RC-Filter an|
; | invertierienden Analogeingang AIN1 entsprechend |
; | Port B Bit 3; Anschluss der zu messenden Analog- |
; | spannung an nichtinvertierenden Analogeingang |
; | Port B Bit 2; Ausgabe für die LEDs an Port C |
; +-----------------------------------------------------+
;
; Geschrieben für und getestet mit AT90S8515 auf STK500
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Konstanten
;
.EQU CycLen = 128 ; Anzahl PWM-Zyklen zum Einschwingen
.EQU CycLen0 = 128 ; Anzahl PWM-Zyklen vor der ersten Messung
;
; Register
;
.DEF rRes = R1 ; Endwert des ADC
.DEF rTmp = R14 ; Temporärwert für ADC
.DEF rSrg = R15 ; Temporärregister für SREG
.DEF rmp = R16 ; Universalregister ohne Int
.DEF rimp = R17 ; Universalregister bei Int
.DEF rFlg = R18 ; Flagregister, Bit 0=ADC fertig
.DEF rBlc = R19 ; Bitlevel-Counter für ADC
.DEF rCcL = R24 ; Cycle Counter für ADC, LSB
.DEF rCcH = R25 ; dto., LSB
;
; Reset- und Interrupt-Vektoren
;
rjmp main ; Reset
reti ; INT0
reti ; INT1
reti ; TC1-Capt
reti ; TC1-CompA
reti ; TC1-CompB
rjmp Tc1Ovflw ; TC1-Ovflw
reti ; TC0-Ovflw
reti ; SPI STC
reti ; UART RX
reti ; UART UDRE
reti ; UART TX
reti ; Ana-Comp
;
; TC1-Overflow am PWM-Zyklusende
;
Tc1Ovflw:
in rSrg,SREG ; Sichern von SREG
sbiw rCcL,1 ; Erniedrige Zykluszähler
brne Tc1OvflwR ; bei ><0 fertig
ldi rCcH,HIGH(CycLen) ; Setze Zyklenzähler
ldi rCcL,LOW(CycLen)
sbis ACSR,ACO ; prüfe Analogcomp-Ausgang
eor rTmp,rBlc ; U zu hoch, lösche letztes Bit
lsr rBlc ; Aktives Bit eins rechts
brcc Tc1OvflwA ; noch nicht fertig
mov rRes,rTmp ; Kopiere das Ergebnis
sbr rFlg,0x01 ; Setze Fertig-Flag
ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn
ldi rCcL,LOW(CycLen0)
clr rTmp ; Leeres Ergebnis
ldi rBlc,0x80 ; Setze Bitzähler
Tc1OvflwA:
or rTmp,rBlc ; setze nächstes Bit
clr rimp ; Setze TC1-PWM-Zyklus
out OCR1AH,rimp
out OCR1AL,rTmp
Tc1OvflwR: ; Rückkehr vom Interupt
out SREG,rSrg ; SREG wieder herstellen
reti
;
; Hauptprogramm-Schleife
;
main:
ldi rmp,HIGH(RAMEND) ; Definiere Stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn
ldi rCcL,LOW(CycLen0)
ldi rBlc,0x80 ; Setze Bitzähler
mov rTmp,rBlc ; Leeres Ergebnis
ldi rmp,0xFF ; Port C auf Output, treibt die LEDs
out DDRC,rmp ; alle Datenrichtungsregister = 1
sbi DDRD,PD5 ; PWM-Ausgang OC1A auf Ausgang setzen
ldi rmp,0b00100000 ; Sleep-mode idle einstellen
out MCUCR,rmp
ldi rmp,0b10000001 ; TC1 auf PWM8 non-invertiert
out TCCR1A,rmp ; in TC1-Kontrollregister A
ldi rmp,0b00000001 ; TC1-clock=System clock
out TCCR1B,rmp ; in TC1-Kontrollregister B
clr rmp ; Pulsweite Rechtecksignal einstellen
out OCR1AH,rmp ; erst das HIGH Byte!
ldi rmp,0x80 ; dann das LOW Byte!
out OCR1AL,rmp
ldi rmp,0b10000000 ; TC1 Overflow Int einschalten
out TIMSK,rmp ; in Timer Int Mask Register
sei ; Reaktion auf Interrupts durch CPU ermöglichen
;
; Hauptprogramm-Loop
;
main1:
sleep ; CPU schlafen legen
nop
sbrs rFlg,0 ; Ready flag Bit 0 abfragen
rjmp main1 ; Nicht ready, schlaf weiter
cbr rFlg,0x01 ; Setze Bit 0 zurück
mov rmp,rRes ; Kopiere Ergebnis in Universalregister
com rmp ; Invertiere alle bits (Lampe invers!)
out PortC,rmp ; an LED Port ausgeben
rjmp main1 ; fertig, schlafen legen
;
; Ende des Programms
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/adc8.html1/20/2009 7:43:08 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/adc8.asm

; +-----------------------------------------------------+
; | 8-Bit-Analog-Digital-Converter mit ATMEL AT90S8515 |
; | auf dem STK500 board, Ausgabe über LEDs |
; | (C)2003 by http://www.avr-asm-tutorial.net |
; | Verwendete Anschlüsse: Ausgang PWM-Rechteckspannung |
; | OC1A an Port D, Bit 5; über dreifach RC-Filter an|
; | invertierienden Analogeingang AIN1 entsprechend |
; | Port B Bit 3; Anschluss der zu messenden Analog- |
; | spannung an nichtinvertierenden Analogeingang |
; | Port B Bit 2; Ausgabe für die LEDs an Port C |
; +-----------------------------------------------------+
;
; Geschrieben für und getestet mit AT90S8515 auf STK500
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Konstanten
;
.EQU CycLen = 128 ; Anzahl PWM-Zyklen zum Einschwingen
.EQU CycLen0 = 128 ; Anzahl PWM-Zyklen vor der ersten Messung
;
; Register
;
.DEF rRes = R1 ; Endwert des ADC
.DEF rTmp = R14 ; Temporärwert für ADC
.DEF rSrg = R15 ; Temporärregister für SREG
.DEF rmp = R16 ; Universalregister ohne Int
.DEF rimp = R17 ; Universalregister bei Int
.DEF rFlg = R18 ; Flagregister, Bit 0=ADC fertig
.DEF rBlc = R19 ; Bitlevel-Counter für ADC
.DEF rCcL = R24 ; Cycle Counter für ADC, LSB
.DEF rCcH = R25 ; dto., LSB
;
; Reset- und Interrupt-Vektoren
;
rjmp main ; Reset
reti ; INT0
reti ; INT1
reti ; TC1-Capt
reti ; TC1-CompA
reti ; TC1-CompB
rjmp Tc1Ovflw ; TC1-Ovflw
reti ; TC0-Ovflw
reti ; SPI STC
reti ; UART RX
reti ; UART UDRE
reti ; UART TX
reti ; Ana-Comp
;
; TC1-Overflow am PWM-Zyklusende
;
Tc1Ovflw:
in rSrg,SREG ; Sichern von SREG
sbiw rCcL,1 ; Erniedrige Zykluszähler
brne Tc1OvflwR ; bei <>0 fertig
ldi rCcH,HIGH(CycLen) ; Setze Zyklenzähler
ldi rCcL,LOW(CycLen)
sbis ACSR,ACO ; prüfe Analogcomp-Ausgang
eor rTmp,rBlc ; U zu hoch, lösche letztes Bit
lsr rBlc ; Aktives Bit eins rechts
brcc Tc1OvflwA ; noch nicht fertig
mov rRes,rTmp ; Kopiere das Ergebnis
sbr rFlg,0x01 ; Setze Fertig-Flag
ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn
ldi rCcL,LOW(CycLen0)
clr rTmp ; Leeres Ergebnis
ldi rBlc,0x80 ; Setze Bitzähler
Tc1OvflwA:
or rTmp,rBlc ; setze nächstes Bit
clr rimp ; Setze TC1-PWM-Zyklus
out OCR1AH,rimp
out OCR1AL,rTmp
Tc1OvflwR: ; Rückkehr vom Interupt
out SREG,rSrg ; SREG wieder herstellen
reti
;
; Hauptprogramm-Schleife
;
main:
ldi rmp,HIGH(RAMEND) ; Definiere Stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rCcH,HIGH(CycLen0) ; Setze Dauer vor Messbeginn
ldi rCcL,LOW(CycLen0)
ldi rBlc,0x80 ; Setze Bitzähler
mov rTmp,rBlc ; Leeres Ergebnis
ldi rmp,0xFF ; Port C auf Output, treibt die LEDs
out DDRC,rmp ; alle Datenrichtungsregister = 1
sbi DDRD,PD5 ; PWM-Ausgang OC1A auf Ausgang setzen
ldi rmp,0b00100000 ; Sleep-mode idle einstellen
out MCUCR,rmp
ldi rmp,0b10000001 ; TC1 auf PWM8 non-invertiert
out TCCR1A,rmp ; in TC1-Kontrollregister A
ldi rmp,0b00000001 ; TC1-clock=System clock
out TCCR1B,rmp ; in TC1-Kontrollregister B
clr rmp ; Pulsweite Rechtecksignal einstellen
out OCR1AH,rmp ; erst das HIGH Byte!
ldi rmp,0x80 ; dann das LOW Byte!
out OCR1AL,rmp
ldi rmp,0b10000000 ; TC1 Overflow Int einschalten
out TIMSK,rmp ; in Timer Int Mask Register
sei ; Reaktion auf Interrupts durch CPU ermöglichen
;
; Hauptprogramm-Loop
;
main1:
sleep ; CPU schlafen legen
nop
sbrs rFlg,0 ; Ready flag Bit 0 abfragen
rjmp main1 ; Nicht ready, schlaf weiter
cbr rFlg,0x01 ; Setze Bit 0 zurück
mov rmp,rRes ; Kopiere Ergebnis in Universalregister
com rmp ; Invertiere alle bits (Lampe invers!)
out PortC,rmp ; an LED Port ausgeben
rjmp main1 ; fertig, schlafen legen
;
; Ende des Programms
;

http://www.avr-asm-tutorial.net/avr_de/quellen/adc8.asm1/20/2009 7:43:10 PM
R/2R-Netzwerk als DAC für einen AVR

Pfad: Home => AVR-Überblick => R/2R-DAC

Tutorial zum Erlernen der


AVR Assembler-Sprache von
AVR-Einchip-
Prozessoren AT90Sxxxx
von ATMEL anhand
praktischer Beispiele.

Einfacher 8-Bit-
Digital-zu-Analog-
Wandler mit einem
R/2R-Netzwerk

Zweck
Die Umwandlung von digitalen Werten in eine Analogspannung kann durch integrierte Schaltungen bewerkstelligt
werden. Eine billigere und weniger anspruchsvolle Lösung ist ein selbstgebautes R/2R-Widerstandsnetzwerk, gefolgt von
einem Operationsverstärker.

Ein R/2R-Netzwerk ist wie im Bild gezeigt aus Widerständen


aufgebaut. Die einzelnen Eingangsbits liegen entweder auf Null Volt
oder auf der Betriebsspannung und speisen über doppelt so große
Widerstände ein wie der vertikale Teil des Netzwerks. Jedes Bit
trägt so seinen spezifischen Teil zur resultierenden
Ausgangsspannung bei. Das funktioniert wirklich, und ziemlich gut!
Kommerzielle Digital-Analog-Wandler haben solche R/2R-
Netzwerke im IC integriert.

Der Ausgang eines AVR liefert nicht sehr viel Strom an seinen
Portausgängen, wenn die Spannungen in der Nähe der
Versorgungsspannungen bleiben sollen. Daher sollten die
Widerstände des R/2R-Netzwerks größer als einige 10 Kiloohm
sein. Um das Netzwerk möglichst gering zu belasten entkoppelt ein
Operationsverstärker das Netzwerk vom weiteren Verbraucher.

Die Widerstandswerte sollten so genau eingehalten werden wie es


vom gesamten Netzwerk erwartet wird. Abweichungen von
Widerstandswerten sind besonders bei den höherwertigen Bits
relevant. Die folgende Tabelle zeigt einige Beispiele für die
schrittweise Spannungssteigerung eines R/2R-Netzwerks mit einer
51k/100k-Kombination. (Die Berechnungen wurden mit einem Free-
Pascal-Programm durchgeführt, der freie Quellcode kann hier
gedowngeloaded) werden.

R2R-Netzwerk Berechnungsprogramm, (C)2004 info !at! avr-asm-tutorial.net


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

Bits Aufloesung: nr=8[bits], Bits=00000000


Spannungen: ub=5.000[V], ul=0.000[V], uh=5.000[V]
Widerstaende: R1= 51k0, R2=100k0

Eingabekombinationen und Ausgabespannungen


00000000: 0.000[V]
00000001: 0.019[V] (Delta= 18.69[mV])
00000010: 0.038[V] (Delta= 19.06[mV])
00000011: 0.056[V] (Delta= 18.69[mV])
00000100: 0.076[V] (Delta= 19.62[mV])
00000101: 0.095[V] (Delta= 18.69[mV])
00000110: 0.114[V] (Delta= 19.06[mV])
00000111: 0.132[V] (Delta= 18.69[mV])
00001000: 0.153[V] (Delta= 20.67[mV])
00001001: 0.172[V] (Delta= 18.69[mV])
00001010: 0.191[V] (Delta= 19.06[mV])
00001011: 0.210[V] (Delta= 18.69[mV])
00001100: 0.229[V] (Delta= 19.62[mV])
00001101: 0.248[V] (Delta= 18.69[mV])
00001110: 0.267[V] (Delta= 19.06[mV])
00001111: 0.286[V] (Delta= 18.69[mV])
00010000: 0.308[V] (Delta= 22.72[mV])
00010001: 0.327[V] (Delta= 18.69[mV])
00010010: 0.346[V] (Delta= 19.06[mV])
00010011: 0.365[V] (Delta= 18.69[mV])
00010100: 0.384[V] (Delta= 19.62[mV])
00010101: 0.403[V] (Delta= 18.69[mV])
00010110: 0.422[V] (Delta= 19.06[mV])
00010111: 0.441[V] (Delta= 18.69[mV])
00011000: 0.462[V] (Delta= 20.67[mV])
00011001: 0.480[V] (Delta= 18.69[mV])
00011010: 0.499[V] (Delta= 19.06[mV])
00011011: 0.518[V] (Delta= 18.69[mV])
00011100: 0.538[V] (Delta= 19.62[mV])
00011101: 0.556[V] (Delta= 18.69[mV])
00011110: 0.575[V] (Delta= 19.06[mV])
00011111: 0.594[V] (Delta= 18.69[mV])
00100000: 0.621[V] (Delta= 26.83[mV])
00100001: 0.640[V] (Delta= 18.69[mV])
00100010: 0.659[V] (Delta= 19.06[mV])
00100011: 0.677[V] (Delta= 18.69[mV])
00100100: 0.697[V] (Delta= 19.62[mV])
00100101: 0.716[V] (Delta= 18.69[mV])
00100110: 0.735[V] (Delta= 19.06[mV])
00100111: 0.753[V] (Delta= 18.69[mV])
00101000: 0.774[V] (Delta= 20.67[mV])
00101001: 0.793[V] (Delta= 18.69[mV])
00101010: 0.812[V] (Delta= 19.06[mV])
00101011: 0.830[V] (Delta= 18.69[mV])
00101100: 0.850[V] (Delta= 19.62[mV])
00101101: 0.869[V] (Delta= 18.69[mV])
00101110: 0.888[V] (Delta= 19.06[mV])
00101111: 0.906[V] (Delta= 18.69[mV])
00110000: 0.929[V] (Delta= 22.72[mV])
...
01111110: 2.446[V] (Delta= 19.06[mV])
01111111: 2.465[V] (Delta= 18.69[mV])
10000000: 2.517[V] (Delta= 51.72[mV])
10000001: 2.535[V] (Delta= 18.69[mV])
10000010: 2.554[V] (Delta= 19.06[mV])
10000011: 2.573[V] (Delta= 18.69[mV])
...

Man beachte den Sprung, wenn Bit 7 High wird! Die Spannung springt dann um mehr als zwei Digits. Das ist für ein 8-
Bit-Netzwerk zu groß, aber akzeptabel für ein 4-Bit-Netzwerk.

Benötigte Hardware
Die Hardware ist einfach zu bauen, es ist ein wahres Widerstands-Grab.

Der CA3140 ist ein Operationsverstärker mit einer FET-Eingangsstufe. Er arbeitet auch bei Eingangsspannungen in der
Nähe der negativen Versorgungsspannung. Man kann auch einen 741 verwenden, aber das hat Konsequenzen (siehe
unten).
Die Betriebsspannung von 5 Volt wird hier über den zehnpoligen Steckverbinder bezogen. Dieser passt direkt zu einem
STK200- oder STK500-Entwicklungsboard. Es ist auch möglich, die Betriebsspannung des Operationsverstärkers aus
einer externen Spannungsquelle zu beziehen. Das hat einige Vorteile, ist aber nicht zwingend.
Anstelle der Parallelschaltung zweier gleich großer Widerstände kann man natürlich auch ähnliche Paare verwenden,
aber das verringert die Genauigkeit bei einem 8-Bit-Netzwerk immens (siehe oben).

Zum Anfang dieser Seite

Anwendung des R/2R-Netzwerks

Einen Sägezahn erzeugen

Das folgende Programm erzeugt eine Sägezahnspannung am R/2R-Netzwerk-Ausgang. Den Quellcode gibt es zum
Download here.

; *************************************************************
; * R/2R-Netzwerk erzeugt eine Saegezahnspannung ueber Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; *************************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
;
ldi rmp,0xFF; Alle Pins von Port D als Ausgang
out DDRD,rmp ; in Datenrichtungsregister
sawtooth:
out PORTD,rmp ; Inhalt von rmp an Port D ausgeben
inc rmp ; erhöhen
rjmp sawtooth ; und weiter fuer immer

Das Ergebnis ist etwas enttäuschend. Sieht nicht wie ein Sägezahn aus,
eher wie eine Holzsäge, mit der Stahl gesägt worden ist.

Der Grund dafür liegt nicht beim R/2R-Netzwerk sondern beim


Operationsverstärker. Er arbeitet nicht so ganz gut in der Nähe der
positiven Betriebsspannung.

Die maximale Ausgangsspannung des R/2R-Netzwerks muss also auf etwa 2.5 Volt begrenzt werden. Das wird per
Software erledigt (Quellcode steht unter diesem Link zum Download).

; *****************************************************
; * R/2R-Netzwerk als Saegezahn ueber Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; *****************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
;
ldi rmp,0xFF; Alle Pins von Port D auf Ausgang
out DDRD,rmp
sawtooth:
out PORTD,rmp ; Inhalt des Registers an Port ausgeben
inc rmp ; um Eins erhoehen
andi rmp,0x7F ; Bit 7 auf Null setzen
rjmp sawtooth ; und so weiter

Das sieht etwas besser aus.

Man beachten, dass wir jetzt Bit 7 des Ports eigentlich nicht mehr
benötigen, er kann fest auf Null gezogen werden, weil er sowieso Null ist.

Hier das Ergebnis, wenn der Operationsverstärker CA3140 mit einem


billigeren 741 ersetzt wird. Der 741 arbeitet weder in der Nähe der
negativen noch in der Nähe der positiven Betriebsspannung. Der
Spannungsbereich des R/2R-Netzwerks müsste entweder weiter
eingeschränkt werden (auf ca. 2 bis 4 Volt) oder es muss eine
symmetrische Versorgung des Opamp her.

Zum Anfang dieser Seite

Eine Dreieckspannung

Eine Dreieckspannung ist ähnlich einfach zu erzeugen: nur hoch und runter zählen. Der Quellcode kann wieder unter
diesem Link gedowngeloaded werden. Die Software gestattet die Einstellung der Frequenz durch Änderung der
Konstanten "delay" und die maximale Amplitude durch "maxAmp".

; ***********************************************************
; * R/2R-Netzwerk produziert eine Dreieckspannung an Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; ***********************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
.DEF rdl = R17 ; Verzoegerungszaehler
;
; Konstanten
;
.EQU maxAmp = 127 ; Maximum Amplitude
.EQU delay = 1 ; Verzoegerung, hoehere Werte machen niedrigere Frequenz
;
ldi rmp,0xFF; Alle Port-D-Pins als Ausgang
out DDRD,rmp
triangle:
clr rmp ; bei Null anfangen
loopup:
out PORTD,rmp ; an Port ausgeben
ldi rdl,delay ; Verzoegerung einstellen
delayup:
dec rdl ; Zaehler herunterzaehlen
brne delayup ; weiter mit zaehlen
inc rmp ; naechstgroesserer Wert
cpi rmp,maxAmp ; mit maximaler Amplitude vergleichen
brcs loopup ; wenn noch nicht erreicht, weiter hoch
loopdwn:
out PORTD,rmp ; Ausgabe rueckwaerts
ldi rdl,delay ; wieder verzoegern
delaydwn:
dec rdl ; herunterzaehlen
brne delaydwn ; weiter verzoegern
dec rmp ; naechstniedrigeren Wert einstellen
brne loopdwn ; wenn noch nicht Null, dann weiter
rjmp triangle ; und wieder von vorne fuer immer

Links wurde die maximale


Amplitude auf 2,5 V
begrenzt, rechts sind die
vollen 5 Volt ausgesteuert.

Zum Anfang dieser Seite

Einen Sinus erzeugen

Mindestens ein Sinus muss jetzt her. Wer denkt, ich schreibe jetzt in Assembler ein Programm zur Sinusberechnung, den
muss ich enttäuschen. Ich mache das auf dem PC in einem kleinen Programm in Free-Pascal (Download hier) und
importiere die resultierende Tabelle (Download hier) in mein Programm (Download hier).

; **********************************************************
; * Produziert einen Sinus an einem R/2R-Netzwerk an PORTD *
; * (C)2005 by avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definition
;
.DEF rmp = R16 ; Multipurpose Register
;
; Beginn des Programms
;
ldi rmp,0xFF ; Alle Pins von Port D sind Ausgang
out DDRD,rmp
ldi ZH,HIGH(2*SineTable) ; Z auf Tabelle im Flash
ldi ZL,LOW(2*SineTable)
clr rmp
loop1:
nop
nop
nop
loop2:
lpm ; Lesen aus der Tabelle
out PORTD,R0 ; Tabellenwert an Port D
adiw ZL,1 ; naechster Tabellenwert
dec rmp ; Ende der Tabelle erreicht?
brne loop1 ; nein
ldi ZH,HIGH(2*SineTable) ; Z wieder auf Tabellenanfang
ldi ZL,LOW(2*SineTable)
rjmp loop2 ; weiter so
;
; Ende Instruktionen
;
; Include der Sinustabelle
;
.INCLUDE "sine8_25.txt"
;
; Ende Programm
;
;
; Sinustabelle fuer 8 Bits D/A
; Tabellenlaenge = 256 Werte
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (mit sinewave.pas erzeugt)
;
Sinetable:
.DB 64,65,67,68,70,72,73,75
.DB 76,78,79,81,82,84,85,87
.DB 88,90,91,92,94,95,97,98
.DB 99,100,102,103,104,105,107,108
.DB 109,110,111,112,113,114,115,116
.DB 117,118,118,119,120,121,121,122
.DB 123,123,124,124,125,125,126,126
.DB 126,127,127,127,127,127,127,127
.DB 128,127,127,127,127,127,127,127
.DB 126,126,126,125,125,124,124,123
.DB 123,122,121,121,120,119,118,118
.DB 117,116,115,114,113,112,111,110
.DB 109,108,107,105,104,103,102,100
.DB 99,98,97,95,94,92,91,90
.DB 88,87,85,84,82,81,79,78
.DB 76,75,73,72,70,68,67,65
.DB 64,62,61,59,58,56,54,53
.DB 51,50,48,47,45,44,42,41
.DB 39,38,36,35,34,32,31,30
.DB 28,27,26,25,23,22,21,20
.DB 19,18,17,15,14,13,13,12
.DB 11,10,9,8,8,7,6,5
.DB 5,4,4,3,3,2,2,2
.DB 1,1,1,0,0,0,0,0
.DB 0,0,0,0,0,0,1,1
.DB 1,2,2,2,3,3,4,4
.DB 5,5,6,7,8,8,9,10
.DB 11,12,13,13,14,15,17,18
.DB 19,20,21,22,23,25,26,27
.DB 28,30,31,32,34,35,36,38
.DB 39,41,42,44,45,47,48,50
.DB 51,53,54,56,58,59,61,62

Das war es schon. Macht einen schönen Sinus. Man glaubt kaum, dass hier
eine digitale Maschinerie am Werk ist und kein sauberer LC-Oszillator.

Unglücklicherweise kann man mit dieser Methode keinen Sinus mit mehr
als 1800 Hz machen, weil vier MHz Takt durch 256 schon nur noch
15.625 ergeben. Und zum Tabellelesen auch der eine oder andere Takt
gebraucht wird.

Zum Anfang dieser Seite

Musiknoten mit dem R/2R-Netzwerk spielen

Das folgende Programm benutzt das R/2R-Netzwerk zum Spielen von Musiknoten mit den Tasten des STK200-Boards.
Es arbeitet ohne Änderung mit einem AT90S8515 mit 4 MHz Takt, den acht Tastenschaltern am Port D und dem R/2R-
Netzwerk an Port B angeschlossen (Download hier).

; ******************************************************************
; * Musik mit dem STK200 und einem R/2R-Netzwerk *
; * PortD hat acht Tasten (active low), PortB generiert die Ausgabe*
; * fuer das R/2R-Netzwerk, spielt Noten wenn die Tasten betaetigt *
; * werden, fuer ATMEL AT90S8515 bei 4 MHz *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; ******************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Konstanten
;
.EQU clock = 4000000 ; Processortakt
.EQU cNSine = 32 ; Tabellelaenge Sinustabelle
;
.DEF rLen = R1 ; Register fuer Dauer der Ausgabe
.DEF rCnt = R2 ; Zaehler fuer die Verzoegerung
.DEF rmp = R16 ; Multipurpose Register
.DEF rTab = R17 ; Zaehler fuer Tabellenlaenge
;
ldi rmp,0xFF ; Alle Bits von Port B Ausgang => R/2R Netzwerk
out DDRB,rmp ; an Datenrichtungsregister
wtloop:
in rmp,PIND ; lese die Tasten
cpi rmp,0xFF ; alle Tasten inaktiv?
breq wtloop ; je, weiter warten bis aktiv
ldi ZH,HIGH(2*MusicTable) ; Z auf Tonhoehentabelle setzen
ldi ZL,LOW(2*MusicTable)
tabloop:
rol rmp ; Rotiere naechstes Bit in Carry
brcc tabfound ; gedrueckte Taste gefunden
adiw ZL,1 ; Z auf nachsten Tabellenwert
rjmp tabloop ; Pruefe naechstes Bit
tabfound:
lpm ; Lese Tonhoehenwert aus Tabelle in R0
mov rlen,R0 ; Kopiere in delay, R0 wird anderweitig benutzt
;
; Spiele einen Ton, bis die Tasten alle inaktiv sind
;
startsine:
ldi ZH,HIGH(2*SineTable) ; Z auf die Sinustabelle setzen
ldi ZL,LOW(2*SineTable)
ldi rTab,cNSine ; Laenge der Sinustabelle
;
; Der folgende Code ist timing-maessig optimiert, damit alle
; Teilschritte gleich lang dauern, die benoetigten Taktzyklen
; sind angegeben, wenn die Instruktion abgearbeitet ist,
; Taktzyklen waehrend Tabellenlesen / Taktzyklen am Tabellenende
;
loopsine:
in rmp,PIND ; 1/- Pruefe ob Tasten noch aktiv ist
cpi rmp,0xFF ; 2/-
breq wtloop ; 3/- Taste nicht mehr aktiv, gehe zurueck
nop ; 4/- verzoegern fuer Synchronisation
loopnext:
lpm ; 7/3 Lese Sinustabelle in R0
out PORTB,R0 ; 8/4 Kopiere zum R/2R-Netzwerk
mov rCnt,rLen ; 9/5 Setze Verzoegerungszaehler
; Verzoegerungsschleife, braucht 3*rLen-1 Taktzyklen
loopdelay:
dec rCnt ; (1) naechster Zaehlerwert
brne loopdelay ; (2/1) noch nicht Null
; 3*rLen+8/3*rLen+4 am Ende der Verzoegerung
adiw ZL,1 ; 3*rLen+10/3*rLen+6 naechster Tabellenwert
dec rTab ; 3*rLen+11/3*rLen+7 Anzahl Tabellenwerte
brne loopsine ; 3*rLen+13/3*rLen+8 naechster Tabellenwert
ldi ZH,HIGH(2*SineTable) ; -/3*rLen+9 Neuanfang Tabelle
ldi ZL,LOW(2*SineTable) ; -/3*rLen+10
ldi rTab,cNSine ; -/3*rLen+11 Laenge der Sinustabelle
rjmp loopnext ; -/3*rLen+13 Neustart (ohne Tasten!)
;
; Tabelle fuer Verzoegerung zur Tonerzeugung der 8 Frequenzen
;
; Frequenz = clock / Tabellenlaenge / ( 3 * rLen + 13 )
; rLen = ( clock /Tabellenlaenge / Frequenz - 13 ) / 3
;
MusicTable:
; f=261.6 293.7 329.6 349.2 392.0 440.0 493.9 523.2 (Sollwert)
.DB 155, 138, 122, 115, 102, 90, 80, 75
; f=261.5 292.7 329.8 349.2 391.9 441.7 494.1 525.2 (Istwert)
; Unterschiede zwischen Soll und Ist wegen Rundung und Aufloesung)
;
; Sinustabelle fuer 8 Bits D/A
; Tabellenlaenge = 32 Werte
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (mit sinewave.pas erzeugt)
;
Sinetable:
.DB 64,76,88,99,109,117,123,126
.DB 128,126,123,117,109,99,88,76
.DB 64,51,39,28,19,11,5,1
.DB 0,1,5,11,19,28,39,51
;
; Ende des Programms
;

Natürlich muss man einen kleinen Lautsprecher oder Ohrhöhrer an den Bufferausgang anschließen. Ohne das bleiben die
schönen Sinuswellen stumm.

Zum Anfang dieser Seite

©2005 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_dac.html1/20/2009 7:43:23 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/sawtooth1.asm

; *************************************************************
; * R/2R-Netzwerk erzeugt eine Saegezahnspannung ueber Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; *************************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
;
ldi rmp,0xFF; Alle Pins von Port D als Ausgang
out DDRD,rmp ; in Datenrichtungsregister
sawtooth:
out PORTD,rmp ; Inhalt von rmp an Port D ausgeben
inc rmp ; erh&ouml;hen
rjmp sawtooth ; und weiter fuer immer

http://www.avr-asm-tutorial.net/avr_de/quellen/sawtooth1.asm1/20/2009 7:43:27 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/sawtooth2.asm

; *****************************************************
; * R/2R-Netzwerk als Saegezahn ueber Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; *****************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
;
ldi rmp,0xFF; Alle Pins von Port D auf Ausgang
out DDRD,rmp
sawtooth:
out PORTD,rmp ; Inhalt des Registers an Port ausgeben
inc rmp ; um Eins erhoehen
andi rmp,0x7F ; Bit 7 auf Null setzen
rjmp sawtooth ; und so weiter

http://www.avr-asm-tutorial.net/avr_de/quellen/sawtooth2.asm1/20/2009 7:43:28 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/triangle.asm

; ***********************************************************
; * R/2R-Netzwerk produziert eine Dreieckspannung an Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; ***********************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose Register
.DEF rdl = R17 ; Verzoegerungszaehler
;
; Konstanten
;
.EQU maxAmp = 127 ; Maximum Amplitude
.EQU delay = 1 ; Verzoegerung, hoehere Werte machen niedrigere Frequenz
;
ldi rmp,0xFF; Alle Port-D-Pins als Ausgang
out DDRD,rmp
triangle:
clr rmp ; bei Null anfangen
loopup:
out PORTD,rmp ; an Port ausgeben
ldi rdl,delay ; Verzoegerung einstellen
delayup:
dec rdl ; Zaehler herunterzaehlen
brne delayup ; weiter mit zaehlen
inc rmp ; naechstgroesserer Wert
cpi rmp,maxAmp ; mit maximaler Amplitude vergleichen
brcs loopup ; wenn noch nicht erreicht, weiter hoch
loopdwn:
out PORTD,rmp ; Ausgabe rueckwaerts
ldi rdl,delay ; wieder verzoegern
delaydwn:
dec rdl ; herunterzaehlen
brne delaydwn ; weiter verzoegern
dec rmp ; naechstniedrigeren Wert einstellen
brne loopdwn ; wenn noch nicht Null, dann weiter
rjmp triangle ; und wieder von vorne fuer immer

http://www.avr-asm-tutorial.net/avr_de/quellen/triangle.asm1/20/2009 7:43:29 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/sine8_25.txt

;
; Sinustabelle fuer 8 Bits D/A
; Tabellenlaenge = 256 Werte
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (mit sinewave.pas erzeugt)
;
Sinetable:
.DB 64,65,67,68,70,72,73,75
.DB 76,78,79,81,82,84,85,87
.DB 88,90,91,92,94,95,97,98
.DB 99,100,102,103,104,105,107,108
.DB 109,110,111,112,113,114,115,116
.DB 117,118,118,119,120,121,121,122
.DB 123,123,124,124,125,125,126,126
.DB 126,127,127,127,127,127,127,127
.DB 128,127,127,127,127,127,127,127
.DB 126,126,126,125,125,124,124,123
.DB 123,122,121,121,120,119,118,118
.DB 117,116,115,114,113,112,111,110
.DB 109,108,107,105,104,103,102,100
.DB 99,98,97,95,94,92,91,90
.DB 88,87,85,84,82,81,79,78
.DB 76,75,73,72,70,68,67,65
.DB 64,62,61,59,58,56,54,53
.DB 51,50,48,47,45,44,42,41
.DB 39,38,36,35,34,32,31,30
.DB 28,27,26,25,23,22,21,20
.DB 19,18,17,15,14,13,13,12
.DB 11,10,9,8,8,7,6,5
.DB 5,4,4,3,3,2,2,2
.DB 1,1,1,0,0,0,0,0
.DB 0,0,0,0,0,0,1,1
.DB 1,2,2,2,3,3,4,4
.DB 5,5,6,7,8,8,9,10
.DB 11,12,13,13,14,15,17,18
.DB 19,20,21,22,23,25,26,27
.DB 28,30,31,32,34,35,36,38
.DB 39,41,42,44,45,47,48,50
.DB 51,53,54,56,58,59,61,62

http://www.avr-asm-tutorial.net/avr_de/quellen/sine8_25.txt1/20/2009 7:43:32 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/sinewave.asm

; **********************************************************
; * Produziert einen Sinus an einem R/2R-Netzwerk an PORTD *
; * (C)2005 by avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "8515def.inc"
;
; Register Definition
;
.DEF rmp = R16 ; Multipurpose Register
;
; Beginn des Programms
;
ldi rmp,0xFF ; Alle Pins von Port D sind Ausgang
out DDRD,rmp
ldi ZH,HIGH(2*SineTable) ; Z auf Tabelle im Flash
ldi ZL,LOW(2*SineTable)
clr rmp
loop1:
nop
nop
nop
loop2:
lpm ; Lesen aus der Tabelle
out PORTD,R0 ; Tabellenwert an Port D
adiw ZL,1 ; naechster Tabellenwert
dec rmp ; Ende der Tabelle erreicht?
brne loop1 ; nein
ldi ZH,HIGH(2*SineTable) ; Z wieder auf Tabellenanfang
ldi ZL,LOW(2*SineTable)
rjmp loop2 ; weiter so
;
; Ende Instruktionen
;
; Include der Sinustabelle
;
.INCLUDE "sine8_25.txt"
;
; Ende Programm
;

http://www.avr-asm-tutorial.net/avr_de/quellen/sinewave.asm1/20/2009 7:43:34 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/musik.asm

; ******************************************************************
; * Musik mit dem STK200 und einem R/2R-Netzwerk *
; * PortD hat acht Tasten (active low), PortB generiert die Ausgabe*
; * fuer das R/2R-Netzwerk, spielt Noten wenn die Tasten betaetigt *
; * werden, fuer ATMEL AT90S8515 bei 4 MHz *
; * (C)2005 by info@avr-asm-tutorial.net *
; ******************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Konstanten
;
.EQU clock = 4000000 ; Processortakt
.EQU cNSine = 32 ; Tabellelaenge Sinustabelle
;
.DEF rLen = R1 ; Register fuer Dauer der Ausgabe
.DEF rCnt = R2 ; Zaehler fuer die Verzoegerung
.DEF rmp = R16 ; Multipurpose Register
.DEF rTab = R17 ; Zaehler fuer Tabellenlaenge
;
ldi rmp,0xFF ; Alle Bits von Port B Ausgang => R/2R Netzwerk
out DDRB,rmp ; an Datenrichtungsregister
wtloop:
in rmp,PIND ; lese die Tasten
cpi rmp,0xFF ; alle Tasten inaktiv?
breq wtloop ; je, weiter warten bis aktiv
ldi ZH,HIGH(2*MusicTable) ; Z auf Tonhoehentabelle setzen
ldi ZL,LOW(2*MusicTable)
tabloop:
rol rmp ; Rotiere naechstes Bit in Carry
brcc tabfound ; gedrueckte Taste gefunden
adiw ZL,1 ; Z auf nachsten Tabellenwert
rjmp tabloop ; Pruefe naechstes Bit
tabfound:
lpm ; Lese Tonhoehenwert aus Tabelle in R0
mov rlen,R0 ; Kopiere in delay, R0 wird anderweitig benutzt
;
; Spiele einen Ton, bis die Tasten alle inaktiv sind
;
startsine:
ldi ZH,HIGH(2*SineTable) ; Z auf die Sinustabelle setzen
ldi ZL,LOW(2*SineTable)
ldi rTab,cNSine ; Laenge der Sinustabelle
;
; Der folgende Code ist timing-maessig optimiert, damit alle
; Teilschritte gleich lang dauern, die benoetigten Taktzyklen
; sind angegeben, wenn die Instruktion abgearbeitet ist,
; Taktzyklen waehrend Tabellenlesen / Taktzyklen am Tabellenende
;
loopsine:
in rmp,PIND ; 1/- Pruefe ob Tasten noch aktiv ist
cpi rmp,0xFF ; 2/-
breq wtloop ; 3/- Taste nicht mehr aktiv, gehe zurueck
nop ; 4/- verzoegern fuer Synchronisation
loopnext:
lpm ; 7/3 Lese Sinustabelle in R0
out PORTB,R0 ; 8/4 Kopiere zum R/2R-Netzwerk
mov rCnt,rLen ; 9/5 Setze Verzoegerungszaehler
; Verzoegerungsschleife, braucht 3*rLen-1 Taktzyklen
loopdelay:
dec rCnt ; (1) naechster Zaehlerwert
brne loopdelay ; (2/1) noch nicht Null
; 3*rLen+8/3*rLen+4 am Ende der Verzoegerung
adiw ZL,1 ; 3*rLen+10/3*rLen+6 naechster Tabellenwert
dec rTab ; 3*rLen+11/3*rLen+7 Anzahl Tabellenwerte
brne loopsine ; 3*rLen+13/3*rLen+8 naechster Tabellenwert
ldi ZH,HIGH(2*SineTable) ; -/3*rLen+9 Neuanfang Tabelle
ldi ZL,LOW(2*SineTable) ; -/3*rLen+10
ldi rTab,cNSine ; -/3*rLen+11 Laenge der Sinustabelle
rjmp loopnext ; -/3*rLen+13 Neustart (ohne Tasten!)
;
; Tabelle fuer Verzoegerung zur Tonerzeugung der 8 Frequenzen
;
; Frequenz = clock / Tabellenlaenge / ( 3 * rLen + 13 )
; rLen = ( clock /Tabellenlaenge / Frequenz - 13 ) / 3
;
MusicTable:
; f=261.6 293.7 329.6 349.2 392.0 440.0 493.9 523.2 (Sollwert)
.DB 155, 138, 122, 115, 102, 90, 80, 75
; f=261.5 292.7 329.8 349.2 391.9 441.7 494.1 525.2 (Istwert)
; Unterschiede zwischen Soll und Ist wegen Rundung und Aufloesung)
;
; Sinustabelle fuer 8 Bits D/A
; Tabellenlaenge = 32 Werte
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (mit sinewave.pas erzeugt)
;
Sinetable:
.DB 64,76,88,99,109,117,123,126
.DB 128,126,123,117,109,99,88,76
.DB 64,51,39,28,19,11,5,1
.DB 0,1,5,11,19,28,39,51
;
; Ende des Programms
;

http://www.avr-asm-tutorial.net/avr_de/quellen/musik.asm1/20/2009 7:43:35 PM
AVR-Hardware-Testroutinen

Pfad: Home => AVR-Übersicht => Software

Tutorial für das Erlernen der


Assemblersprache von
AVR-Einchip-Prozessoren
AT90Sxxxx
von ATMEL anhand geeigneter
praktischer Beispiele.
Spezielles Software-Know-
How

(Die Links auf die *.asm-Dateien zum Herunterladen mit gedrückter Shift-Taste anklicken.)
HTML- ASM-
Erläuterung zum Inhalt
Format Format
Liest die Tasten und wandelt die Nummer der Taste über eine Liste im
Programmspeicher in die Anzahl an LEDs um und beleuchtet diese. (Taste 0 = 8
LPM LPM
Stück). Ein ziemlich unnützes Programm, aber es demonstriert neben dem LPM-
Befehl auch das Rollen und Springen.
Sprünge aus dem Stack heraus vornehmen. Die Unterprogrammaufrufe erfolgen
nicht über den RCALL-Befehl, sondern über den Stack. D.h. zuerst wird die
JUMP JUMP Rücksprungadresse auf dem Stack abgelegt, dann die Adresse des
Unterprogrammes, das aufgerufen werden soll. Der Sprung und der Rücksprung
erfolgen dann über den RET- Befehl. Etwas trickreiche Programmierkunst!
Makros verwenden. Sinnloses Beispiel zum Erlernen, wie ein Makro in den
MAC1 MAC1
Assembler-Quelltext gelangt und was beim Assemblieren passiert.
Makros verwenden. Sprungziele in Makros nach innerhalb und ausserhalb des
MAC2 MAC2
Makros anwenden. Sinnloses Testprogramm.
Makros verwenden. Makro mit Übergabe eines Parameters an das Makro.
MAC3 MAC3
Sinnloses Testprogramm zum Lernen.
©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/avr_soft.html1/20/2009 7:43:36 PM
AVR-Software-Knowhow: <A HREF="beginner/register.html#LPM">LPM</A>-Befehl

Pfad: Home => AVR-Übersicht => Software => LPM-Befehl

; Testet den LPM-Befehl zum Auslesen von


Bytes aus dem Programmspeicher
; Liest die Tasten und wandelt die Nummer der Taste
; über eine Liste im Programmspeicher in die Anzahl
; an LEDs um und beleuchtet diese. (Taste 0 = 8 Stück)
; Ein ziemlich unnützes Programm, aber es demonstriert
; neben dem LPM-Befehl auch das Rollen und Springen.
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Register
;
.DEF erg=R0 ; Der LPM-Befehl wirkt ausschliesslich auf R0
.DEF mpr=R16 ; Multifunktionsregister
;
; Verwendet werden auch die Register ZL (R30) und ZH (R31).
; Dies wird im 8515def.inc definiert, daher braucht es hier nicht.
;

; Reset-/Interrupt-Vektor

;
RJMP main
;
main: CLR mpr ; Lade 0 in Register mpr
OUT DDRD,mpr ; alle D-Ports sind Eingang Schalter
DEC mpr ; Lade FF in Register B
OUT DDRB,mpr ; Alle B-Ports sind Ausgang LEDs
OUT PORTD,mpr ; Alle Pullups auf D einschalten

loop: LDI ZL,LOW(liste2) ; Registerpaar Z zeigt auf das


LDI ZH,HIGH(liste2) ; erste Byte (FF) in der Liste
IN mpr,PIND ; Lese Schalter aus
CPI mpr,0xFF ; Alle Schalter aus? Alle LEDs aus!
BREQ ;lesen
incp: INC ZL ;Zeige mit LSB auf nächstes Byte der Liste
BRNE rolle ;kein Überlauf des MSB, weiter
INC ZH ;MSB übergelaufen, eins weiter
rolle: ROR mpr ;schiebe Bit 0 in das Carry-Flag
BRLO incp ; Carry=1, nicht gedrückt, weiter in der Liste
lesen: LPM ; Lese das Byte, auf das Zeiger Z zeigt in Register R0
OUT PORTB,erg ; Gib Byte auf LEDs aus
RJMP loop ; Im Kreis drehen
;
; Die Liste mit den Lampenkombinationen, jedes Byte entspricht einem
; Schalter.
; Die Werte müssen jeweils wortweise angegeben werden, weil bei der
; Verwendung von .DB xx immer automatisch ein Null-Byte mitgespeichert
; würde! Es geht aber auch .DB xx,yy! Die werden zu einem Wort ver-
; knüpft. Dasselbe gilt bei Texten mit .DB "abcd...": Geradzahlige An-
; zahlen gehen, ungeradzahlige kriegen ein Nullbyte zusätzlich!
;
liste:
.DW 0xFEFF ; 1 Lampe, 0 Lampen (0 ist hinten, 1 vorne!)
.DW 0xF8FC ; 3 Lampen, 2 Lampen
.DW 0xE0F0 ; 5 Lampen, 4 Lampen
.DW 0x80C0 ; 7 Lampen, 6 Lampen
;
.EQU liste2=liste*2 ; Wird gebraucht, weil die Adresse
; wortweise organisiert ist, die Werte aber
; byteweise gelesen werden sollen

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testlpm.html1/20/2009 7:43:38 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testlpm.asm

; Testet den LPM-Befehl zum Auslesen von Bytes


; aus dem Programmspeicher
;
; Liest die Tasten und wandelt die Nummer der Taste
; über eine Liste im Programmspeicher in die Anzahl
; an LEDs um und beleuchtet diese. (Taste 0 = 8 Stück)
; Ein ziemlich unnützes Programm, aber es demonstriert
; neben dem LPM-Befehl auch das Rollen und Springen.
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Register
;
.DEF erg=R0 ; Der LPM-Befehl wirkt ausschliesslich auf R0
.DEF mpr=R16 ; Multifunktionsregister
;
; Verwendet werden auch die Register ZL (R30) und ZH (R31).
; Dies wird im 8515def.inc definiert, daher braucht es hier nicht.
;
; Reset-/Interrupt-Vektor
;
rjmp main
;
main:
clr mpr ; Lade 0 in Register mpr
out DDRD,mpr ; alle D-Ports sind Eingang Schalter
dec mpr ; Lade FF in Register B
out DDRB,mpr ; Alle B-Ports sind Ausgang LEDs
out PORTD,mpr ; Alle Pullups auf D einschalten
loop:
ldi ZL,LOW(liste2) ; Registerpaar Z zeigt auf das
ldi ZH,HIGH(liste2) ; erste Byte (FF) in der Liste
in mpr,PIND ; Lese Schalter aus
cpi mpr,0xFF ; Alle Schalter aus? Alle LEDs aus!
breq lesen
incp:
inc ZL ; Zeige mit LSB auf nächstes Byte der Liste
brne rolle ; Kein Überlauf des MSB, weiter
inc ZH ; MSB übergelaufen, eins weiter
rolle:
ror mpr ; Schiebe Bit 0 in das Carry-Flag
brlo incp ; Carry=1, nicht gedrückt, weiter in der Liste
lesen:
lpm ; Lese das Byte, auf das Zeiger Z zeigt in Register R0
out PORTB,erg ; Gib Byte auf LEDs aus
rjmp loop ; Im Kreis drehen
;
; Die Liste mit den Lampenkombinationen, jedes Byte entspricht einem
; Schalter.
; Die Werte müssen jeweils wortweise angegeben werden, weil bei der
; Verwendung von .DB xx immer automatisch ein Null-Byte mitgespeichert
; würde! Es geht aber auch .DB xx,yy! Die werden zu einem Wort ver-
; knüpft. Dasselbe gilt bei Texten mit .DB "abcd...": Geradzahlige An-
; zahlen gehen, ungeradzahlige kriegen ein Nullbyte zusätzlich!
;
liste:
.DW 0xFEFF ; 1 Lampe, 0 Lampen (0 ist hinten, 1 vorne!)
.DW 0xF8FC ; 3 Lampen, 2 Lampen
.DW 0xE0F0 ; 5 Lampen, 4 Lampen
.DW 0x80C0 ; 7 Lampen, 6 Lampen
;
.EQU liste2=liste*2 ; Wird gebraucht, weil die Adresse
; wortweise organisiert ist, die Werte aber
; byteweise gelesen werden sollen
;

http://www.avr-asm-tutorial.net/avr_de/quellen/testlpm.asm1/20/2009 7:43:40 PM
AVR-Hardware-Tutorium, RAM-JUMP

Pfad: Home => AVR-Übersicht => Software => JUMP-Befehl

; Testet Unterprogrammaufrufe über den Stack

;
; Die Unterprogrammaufrufe erfolgen nicht über den RCALL-
; Befehl, sondern über den Stack. D.h. zuerst wird die
; Rücksprungadresse auf dem Stack abgelegt, dann die Adresse
; des Unterprogrammes, das aufgerufen werden soll. Der
; Sprung und der Rücksprung erfolgen dann über den RET-
; Befehl.
; Diese Adressierungsart ist für Unterprogrammaufrufe aus
; Tabellen günstig, weil man die Adressen dann aus einer
; Tabellenspalte auslesen kann.
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
.DEF mpr=R16 ; Wie immer ein allgemeines Arbeitsregister
;

; Reset-/Interrupt-Vektortabelle

;
RJMP main
;
main: LDI mpr,HIGH(RAMEND) ; Stack einrichten
OUT SPH,mpr
LDI mpr,LOW(RAMEND)
OUT SPL,mpr

LDI mpr,LOW(retret) ; Lege Rücksprungadresse auf stack


PUSH mpr
LDI mpr,HIGH(retret)
PUSH mpr

LDI mpr,LOW(testup) ; Lege Sprungadresse auf stack


PUSH mpr
LDI mpr,HIGH(testup)
PUSH mpr

RET ; Springe zum Unterprogramm


;

; Das anzuspringende Rücksprungprogramm macht alle


Lampen an
;
retret: LDI mpr,0x00 ; Mache alle Lampen an, wenn erfolgreich
OUT PORTB,mpr
loop: RJMP loop ; Anhalten
;
;

; Testprogramm, das angesprungen werden soll


;
testup: LDI mpr,0xFF ; Alle Lampentreiber auf Ausgabe
OUT DDRB,mpr
RET ; Rücksprung an die Aufrufadresse

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testjmp.html1/20/2009 7:43:42 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testjmp.asm

; Testet Unterprogrammaufrufe über den Stack


;
; Die Unterprogrammaufrufe erfolgen nicht über den RCALL-
; Befehl, sondern über den Stack. D.h. zuerst wird die
; Rücksprungadresse auf dem Stack abgelegt, dann die Adresse
; des Unterprogrammes, das aufgerufen werden soll. Der
; Sprung und der Rücksprung erfolgen dann über den RET-
; Befehl.
; Diese Adressierungsart ist für Unterprogrammaufrufe aus
; Tabellen günstig, weil man die Adressen dann aus einer
; Tabellenspalte auslesen kann.
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
.DEF mpr=R16 ; Wie immer ein allgemeines Arbeitsregister
;
; Reset-/Interrupt-Vektortabelle
;
rjmp main
;
main:
ldi mpr,HIGH(RAMEND) ; Stack einrichten
out SPH,mpr
ldi mpr,LOW(RAMEND)
out SPL,mpr
ldi mpr,LOW(retret) ; Lege Rücksprungadresse auf stack
push mpr
ldi mpr,HIGH(retret)
push mpr
ldi mpr,LOW(testup) ; Lege Sprungadresse auf stack
push mpr
ldi mpr,HIGH(testup)
push mpr
ret ; Springe zum Unterprogramm
;
; Das anzuspringende Rücksprungprogramm macht alle Lampen an
;
retret:
ldi mpr,0x00 ; Mache alle Lampen an, wenn erfolgreich
out PORTB,mpr
loop:
rjmp loop ; Anhalten
;
;
; Testprogramm, das angesprungen werden soll
;
testup:
ldi mpr,0xFF ; Alle Lampentreiber auf Ausgabe
out DDRB,mpr
ret ; Rücksprung an die Aufrufadresse

http://www.avr-asm-tutorial.net/avr_de/quellen/testjmp.asm1/20/2009 7:43:43 PM
AVR-<A HREF="beginner/werkzeuge.html#assembler">Assembler</A>-Makros erlernen, Beispiel 1

Pfad: Home => AVR-Übersicht => Software => Makro-Beispiel 1

Assembler-Quellcode des Makro-Befehls


; *****************************************************
; * Demonstriert den Gebrauch von Makros beim ATMEL *
; * Assembler, nur ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehlerberichte an info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Benutzte Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Der folgende Code ist ein Makro, das in den Code
; eingefügt werden kann, wann immer er benötigt wird.
; Immer wenn die gleiche Sequenz benötigt wird, wird
; dieses Makro aufgerufen. Wenn der Code nicht als Unter-
; programm aufgerufen werden kann, dann ist ein Makro
; fällig.
;
.MACRO TestMacro
Inc mpr
Inc mpr
Inc mpr
.ENDMACRO
;
;
; Beginn des Hauptprogrammes
;
LDI mpr,0xFF ; PortB (LEDs) ist Ausgang
OUT DDRB,mpr ; an Datenrichtungsregister
CLR mpr ; Setze register Null
TestMacro ; Füge das Makro ein (drei INCs)
TestMacro ; Noch mal das Makro (noch mal drei INC)
COM mpr ; Invertieren des Ergebnisses zur Anzeige
OUT PORTB,mpr ; und an die LEDs ausgeben
loop: RJMP loop ; und ab in eine Schleife.
;
; Assemblieren sollte zu 11 Worten Binär-Code führen, weil
; das TestMacro zu je drei Worten Code aufgeblasen wird, also sechs mal
; der INC-Befehl in den Code geschrieben wird.
;
; Nach der Ausführung sind die LEDs PB.1 and PB.2 angeschaltet,
; alle anderen ausgeschaltet. Das Ergebnis ist Dezimal 6 oder
; 0000.0110 binär!
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testmac1.html1/20/2009 7:43:44 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testmac1.asm

; *****************************************************
; * Demonstriert die Verwendung von Makros mit ATMEL *
; * AVR Assembler, nur ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehlerberichte an info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Benutzte Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Das folgende Codestück ist ein Makro. Es kann in
; das Programm aufgenommen werden, so oft man es
; benötigt. Immer wenn die gleiche Sequenz benötigt
; wird, läßt sich ein Makro dafür einsetzen. Anders als
; bei einem Unterprogramm wird der gleiche Code mehrfach
; eingefügt, immer wenn das Makro aufgerufen wird.
;
.MACRO TestMacro
inc mpr
inc mpr
inc mpr
.ENDMACRO
;
;
; Beginn des Hauptprogrammes
;
ldi mpr,0xFF ; PortB (LEDs) ist Ausgang
out DDRB,mpr ; an Datenrichtungsregister
clr mpr ; Setze Register Null
testmacro ; Füge das Makro ein (drei mal INC)(three INCs)
testmacro ; Noch einmal (noch drei INC)here (another 3)
com mpr ; Invertiere das Ergebnisdisplay it
out PORTB,mpr ; und zeige es auf den LEDs anLEDs
loop: RJMP loop ; und ab in die Endlosschleife
;
; Nach dem Assemblieren sollte ein 11 Worte langes
; Binärprogramm resultieren, da die zwei Makros sechs
; INC-Befehle in den Code einfügen.
;
; Nach der Ausführung sollten die LEDs PB.1 and PB.2 an,
; alle anderen aus sein (Ergebnis = 6 ist Binär 0000.0110)!
;

http://www.avr-asm-tutorial.net/avr_de/quellen/testmac1.asm1/20/2009 7:43:46 PM
AVR-<A HREF="beginner/werkzeuge.html#assembler">Assembler</A>-Makros erlernen, Beispiel 2

Pfad: Home => AVR-Übersicht => Software => Makro-Beispiel 2

Assembler Quellcode von Makro 2


; *****************************************************
; * Sprungziele innerhalb eines Makro: Es geht! *
; * Demonstriert den Gebrauch von Makros beim ATMEL *
; * Assembler, nur ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehlerberichte an info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Benutzte Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Das folgende Makro enthält ein Sprungziel innerhalb des Makros
; (mjmp) und ein Sprung zu einem Ziel ausserhalb des Makros.
; Beide Sprünge werden vom Assembler korrekt übersetzt.
;
.MACRO TestMacro
Inc mpr ; Erhöhe das Register mpr
BRNE mjmp ; Wenn kein Überlauf, springe
RJMP ovf ; Springe wenn Überlauf
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Beginn des Hauptprogrammes
;
LDI mpr,0xFF ; Setze PortB (LEDs) als Ausgang
OUT DDRB,mpr ; an Datenrichtungsregister
;
LDI mpr,0xFE ; Setze Register mpr auf 254
TestMacro ; Füge das Makro ein (ein INC)
TestMacro ; Füge es noch mal ein (weiterer INC)
; Weil bei der zweiten Erhöhung ein Überlauf eingetreten sein muss wird der
; folgende Code nie ausgeführt. Wenn er ausgeführt würde, würden alle LEDs
; eingeschaltet werden.
;
outp: OUT PORTB,mpr
loop: RJMP loop ; und ab in die Endlosschleife.
;
; Der Überlauf ist passiert und dieser Code wird ausgeführt:
;
ovf: LDI mpr,0xFF ; Alle LEDs aus
OUT PORTB,mpr ; an Port B
RJMP loop ; Zur Endlosschleife
;
; Nach der Ausführung sind alle LEDs PB.0 to PB.7 aus.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testmac2.html1/20/2009 7:43:47 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testmac2.asm

; *****************************************************
; * Sprungziele innerhalb eines Makros: Es geht! *
; * Zeigt die Anwendung von Makros mit dem ATMEL AVR *
; * Assembler, nur ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehler bitte an info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Verwendete Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Der folgende Code ist ein Makro, das einen Sprung
; zu einem Ziel innerhalb und einen Sprung zu einem
; Ziel ausserhalb des Makros enthält. Beide Befehle
; werden vom Assembler korrekt übersetzt.
;
.MACRO TestMacro
inc mpr ; Erhöhe das Register mpr
brne mjmp ; Wenn kein Überlauf, dann überspringe
rjmp ovf ; Springe zu Ziel ausserhalb des Makros
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Beginn des Hauptprogrammes
;
ldi mpr,0xFF ; PortB (LEDs) ist Ausgang
out DDRB,mpr ; an Datenrichtungsregister
;
ldi mpr,0xFE ; Setze Register auf 254
testmacro ; Füge das Makro einmal ein (1xINC)
testmacro ; Füge es noch einmal ein (+1xINC)
; Da bei der Ausführung bis hier ein Überlauf passiert sein muss,
; wird der nun folgende Code nicht ausgeführt. Wenn er ausgeführt
; würde, würden alle LEDs an sein.
;
outp:
out PORTB,mpr
loop:
rjmp loop ; und Ende in einer Schleife
;
; Der Überlauf ist passiertund dieser Code wird ausgeführt:
;
ovf:
ldi mpr,0xFF ; Alle LEDs ausschalten
out PORTB,mpr ; auf Port B
rjmp loop ; Springe zur Endlosschleife
;
; Nach der Ausführung sollten alle LEDs PB.0 to PB.7 aus sein.

http://www.avr-asm-tutorial.net/avr_de/quellen/testmac2.asm1/20/2009 7:43:48 PM
AVR-<A HREF="beginner/werkzeuge.html#assembler">Assembler</A>-Makros erlernen, Beispiel 3

Pfad: Home => AVR-Übersicht => Software => Makro-Beispiel 3

Assembler Quellcode von Makro 3


; *****************************************************
; * Einen Parameter an ein Makro übergeben: Geht so! *
; * Zeigt den Gebrauch von Makros beim ATMEL AVR- *
; * Assembler, nur ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehlerberichte an info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Benutzte Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Das folgende Makro enthält ein Sprungziel innerhalb des
; Makros und erhält den Zählerstand mit dem ersten Parameter
; übergeben (@0).
;
.MACRO TestMacro
LDI mpr,@0 ; Setze mpr auf Wert des 1. Parameters
Inc mpr ; Erhöhe um eins
BRNE mjmp ; Wenn kein Überlauf überspringe
RJMP ovf ; Springe wenn Überlauf
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Beginn des Hauptprogrammes
;
LDI mpr,0xFF ; PortB (LEDs) ist Ausgang
OUT DDRB,mpr ; an Datenrichtungsregister
;
LDI mpr,0xFE ; Setze mpr auf 254
; Hier kommt das Makro: 0xFF wird übergeben, dann um Eins erhöht.
; Wenn dann Null rauskommt, springt die Ausführung nach ovf.
;
TestMacro(0xFF) ; Füge das Makro mit dem Parameter FF ein
;
; Weil ein Überlauf passiert sein muss bei der letzten Erhöhung
; sollte der folgende Code niemals ausgeführt werden. Wenn er
; doch ausgeführt würde, wären alle LEDs an.
;
outp: OUT PORTB,mpr
loop: RJMP loop ; und in die Endlosschleife
;
; Der Überlauf sollte passiert sein und dieser Code wird ausgeführt:
;
ovf: LDI mpr,0xFF ; Lösche alle LEDs
OUT PORTB,mpr ; an Port B
RJMP loop ; Springe zur Endlosschleife
;
; Nach der Ausführung sollten alle LEDs PB.0 to PB.7 aus sein.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/testmac3.html1/20/2009 7:43:50 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testmac3.asm

; *****************************************************
; * Einen Parameter an ein Makro übergeben: geht! *
; * Zeigt den Gebrauch von Makros beim ATMEL AVR- *
; * Assembler, einfach ein Testprogramm für das *
; * ATMEL STK200 Board, (C) 2000 Gerhard Schmidt *
; * Fehlerberichte an info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Verwendete Register
;
.DEF mpr=R16 ; Vielzweckregister
;
; Das folgende Makro enthält ein Sprungziel innerhalb des
; Makros und erhält den Zählerstand mit dem ersten Parameter
; übergeben (@0).
;
.MACRO TestMacro
ldi mpr,@0 ; Setze mpr auf den Wert des ersten Parameters
inc mpr ; Erhöhe um eins
brne mjmp ; Wenn kein Überlauf, überspringe nächsten Befehl
rjmp ovf ; Springe, wenn Überlauf erfolgt.
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Beginn des Hauptprogrammes
;
ldi mpr,0xFF ; PortB (LEDs) ist Ausgang
out DDRB,mpr ; an Datenrichtungsregister
;
ldi mpr,0xFE ; Setze Register auf 254
; Hier kommt das Makro: 0xFF wird übergeben, dann um Eins erhöht.
; Wenn dann Null rauskommt, springt die Ausführung nach ovf.
;
testmacro(0xff) ; Füge das Makro mit dem Parameter FF ein
;
; Weil ein Überlauf passiert sein muss bei der letzten Erhöhung
; sollte der folgende Code niemals ausgeführt werden. Wenn er
; doch ausgeführt würde, wären alle LEDs an.
;
outp:
out PORTB,mpr
loop:
rjmp loop ; und in eine Endlaosschleife
;
; Der Überlauf sollte passiert sein und dieser Code wird ausgeführt:
;
ovf:
ldi mpr,0xFF ; Alle LEDs aus
out PORTB,mpr ; und an Port B
rjmp loop ; Springe zur Endlosschleife
;
; Nach der Ausführung sind alle LEDs PB.0 bis PB.7 aus.

http://www.avr-asm-tutorial.net/avr_de/quellen/testmac3.asm1/20/2009 7:43:51 PM
Anschluss einer Tastatur an einen AVR

Pfad: Home => AVR-Übersicht => Keyboard

Anschluss einer 12-er-Tastatur an einen AVR


Diese Seite zeigt, wie eine handelsübliche 12-er-Tastatur an einen AVR angeschlossen und per
Assembler-Software ausgelesen werden kann. Die Abschnitte:

1. Funktionsweise der Tastatur


2. AVR: I/O-Anschlussmatrix einzeln
3. AVR: Anschluss an einen ADC mit Widerstands-Matrix

1. Funktionsweise der Tastatur


12-er-Tastaturen sind Schalter, die über eine Matrix von Zeilen
(Rows) und Spalten (Columns) miteinander verbunden sind.
Wird die Taste "1" gedrückt, dann ist die Spalte 1 mit der Zeile
1 verbunden, ist "2" gedrückt, dann Spalte 2 mit Reihe 1, usw..

Um herauszufinden, ob irgendeine der 12 Tasten


gedrückt ist, würde es reichen, die drei Spalten mit Null
Volt zu verbinden und die vier Zeilen zu verbinden und
über einen Pull-Up-Widerstand von z.B. 10 kΩ mit
Plus zu verbinden. Der Output hat ohne gedrückte
Taste Plus-Potential. Jede gedrückte Taste bewirkt
dann, dass der Output auf Null Volt gezogen wird.

Um auch noch fest zu stellen, welche der 12 Tasten gedrückt ist, wären z.B. nacheinander die drei
Spaltenanschlüsse auf Null Volt zu bringen (die beiden anderen jeweils auf Plus) und das Ergebnis an
den vier Zeilenanschlüssen abzulesen. Ist einer der vier Zeilenanschlüsse auf Null, muss die
Maschinerie anhalten und den aktuellen Spaltenanschluss sowie das Ergebnis der Zeilenanchlüsse in
den Code einer gedrückten Taste umwandeln. Etwa so:
Column Row Key
Col1 Col2 Col3 Row1 Row2 Row3 Row4 Zeichen Binärcode
0 0 0 1 1 1 1 (Keins) 1111
0 1 1 0 1 1 1 1 0001
1 0 1 0 1 1 1 2 0010
1 1 0 0 1 1 1 3 0011
0 1 1 1 0 1 1 4 0100
1 0 1 1 0 1 1 5 0101
1 1 0 1 0 1 1 6 0110
0 1 1 1 1 0 1 7 0111
1 0 1 1 1 0 1 8 1000
1 1 0 1 1 0 1 9 1001
0 1 1 1 1 1 0 * 1010
1 0 1 1 1 1 0 0 0000
1 1 0 1 1 1 0 # 1011
Um eine solche Tastatur mit diskreten Bauteilen auslesbar zu machen, braucht es mindestens:

● einen Oszillator mit Schieberegister und Start/Stop zur Erzeugung der Spaltensignale,
● Feststellung, ob einer der vier Zeilenanschlüsse Null ist,
● Umkodierer für die Auswertung der sieben Signale.

Oder ein fertiges IC, das das alles macht. Oder eben einen Mikrokontroller.

An den Seitenanfang

2. AVR: I/O-Anschlüssmatrix einzeln


Eine Tastaturmatrix kann direkt und ohne weitere Bauteile an
einen Mikrokontroller angeschaltet werden.
Im Beispiel sind dies die unteren sieben I/O-Pins des Ports B.
Andere Ports lassen sich ebenso verwenden.
Die Ports PB4..PB6 werden als Ausgänge definiert und liefern
die Spalten-Nullen. Die Ports PB0..PB3 dienen zum Einlesen
der Zeilenergebnisse. Die Pull-Up-Widerstände der Ports PB0..
PB3 werden per Software zuschaltet, externe Widerstände sind
unnötig.

Das folgende Software-Beispiel zeigt zunächst das Initiieren der


Ports. Sie wird nur ein Mal zu Beginn des AVR-Programms
ausgeführt.

Init-Routine

;
; Init Keypad-I/O
;
.DEF rmp = R16 ; ein Hilfsregister definieren
; Ports definieren
.EQU pKeyOut = PORTB ; Ausgabe und Pull-Ups
.EQU pKeyInp = PINB ; Tastatur lesen
.EQU pKeyDdr = DDRB ; Datenrichtungsregister
; Init-Routine
InitKey:
ldi rmp,0b01110000 ; Datenrichtungsregister
out pKeyDdr,rmp ; des Keyports setzen
ldi rmp,0b00001111 ; Pull-Up-Widerstände
out pKeyOut,rmp ; an den Eingängen

Tastendruck feststellen

Die folgende Routine stellt zunächst fest, ob irgendeine Taste gedrückt ist. Sie wird im
Programmverlauf regelmäßig wiederholt, z.B. in einer Verzögerungsschleife oder Timer-gesteuert.

;
; Check any key pressed
;
AnyKey:
ldi rmp,0b00001111 ; PB4..PB6=Null, pull-Up-Widerstände
out pKeyOut,rmp ; an den Eingängen PB0..PB3
in rmp,pKeyInp ; Tastaturport lesen
ori rmp,0b11110000 ; alle oberen Bits auf Eins
cpi rmp,0b11111111 ; alle Bits = Eins?
breq NoKey ; ja, keine Taste gedrückt

Gedrückte Taste feststellen

Jetzt ist der Auslesevorgang dran. Nacheinander werden PB6, PB5 und PB4 Null gesetzt und PB0..
PB3 auf Nullen geprüft. Das Registerpaar Z (ZH:ZL) zeigt dabei auf eine Tabelle mit den
Tastencodes. Es zeigt am Ende auf den identifizierten Tastencode, der mit der Instruktion LPM aus
dem Flash-Memory in das Register R0 gelesen wird.

;
; Identifiziere gedrueckte Taste
;
ReadKey:
ldi ZH,HIGH(2*KeyTable) ; Z ist Zeiger auf Tastencode
ldi ZL,LOW(2*KeyTable)
; read column 1
ldi rmp,0b00111111 ; PB6 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; lese Zeile
ori rmp,0b11110000 ; obere Bits maskieren
cpi rmp,0b11111111 ; ein Key in dieser Spalte?
brne KeyRowFound ; Spalte gefunden
adiw ZL,4 ; Spalte nicht gefunden, Z vier Keys weiter
ldi rmp,0b01011111 ; PB5 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; wieder Zeile lesen
ori rmp,0b11110000 ; obere Bits maskieren
cpi rmp,0b11111111 ; ein Key in dieser Spalte?
brne KeyRowFound ; Spalte gefunden
adiw ZL,4 ; Spalte nicht gefunden, Z vier Keys weiter
ldi rmp,0b01101111 ; PB4 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; letzte Zeile lesen
ori rmp,0b11110000 ; obere Bits maskieren
cpi rmp,0b11111111 ; ein Key in dieser Spalte?
breq NoKey ; wider Erwarten auch hier nicht gefunden
KeyRowFound: ; Spalte ist gefunden, identifiziere Zeile
lsr rmp ; schiebe Bit 0 in das Carry-Flag
brcc KeyFound
adiw ZL,1 ; zeige auf naechsten Tastencode
rjmp KeyRowFound ; weiter schieben
KeyFound:
lpm ; lese keycode nach R0
rjmp KeyProc ; hier weiter mit Key-Verarbeitung
NoKey:
rjmp NoKeyPressed ; keine Taste gedrueckt
;
; Tabelle fuer Code Umwandlung
;
KeyTable:
.DB 0x0A,0x07,0x04,0x01 ; Erste Spalte, Tasten *, 7, 4 und 1
.DB 0x00,0x08,0x05,0x02 ; Zweite Spalte, Tasten 0, 8, 5 und 2
.DB 0x0B,0x09,0x06,0x03 ; Dritte Spalte, Tasten #, 9, 6 und 3

Entprellen

In den Routinen KeyProc und NoKeyPressed muss natürlich noch ein Entprellen der Tasten erfolgen.
Also z.B. muss in der KeyProc-Routine eine Tastenoperation erst dann ausgeführt werden, wenn die
gleiche Taste 50 Millisekunden lang gedrückt ist. In der NoKeyPressed-Routine kann der dazu
verwendete Zähler zurück gesetzt werden. Da das Timing der Entprellung auch noch von anderen
Bedürfnissen abhängig sein kann, ist es hier nicht eingearbeitet.

Hinweise, Nachteile

In den Software-Beispielen ist zwischen der Ausgabe der Column-Adresse und dem Einlesen der
Row-Information nur ein Takt Zeit gelassen. Bei hohen Taktfrequenzen und/oder langen Leitungen
zwischen Tastatur und Prozessor ist es notwendig, zwischen den Out- und In-Instruktionen mehr Zeit
zu lassen (z.B. durch Einfügen von NOP-Instruktionen).
Die internen Pull-Ups liegen bei Werten um 50 kΩ. Bei langen Leitungen und in hoch
feldverseuchter Umgebung kann es unter Umständen zum Fehlansprechen der Tastatur kommen. Wer
es weniger sensibel haben will, kann noch externe Pull-Ups dazu schalten.

Der Nachteil der Schaltung ist, dass sie sieben Port-Leitungen exklusiv benötigt. Die Lösung über
einen AD-Wandler-Kanal und ein Widerstands-Netzwerk (Abschnitt 3) ist da viel sparsamer.

An den Seitenanfang

3. Anschluss an einen ADC mit Widerstands-Matrix

Die meisten Tiny- und Mega-AVR-Typen haben heutzutage


AD-Wandler an Bord. Sie sind daher ohne größere
Klimmzüge dazu in der Lage, Analogspannungen zu messen
und mit 10 Bits Genauigkeit aufzulösen. Wer also I/O-Ports
sparen will, muss die Tastatur nur dazu bringen, ein
Analogsignal zu liefern. Das macht z.B. eine
Widerstandsmatrix.

Widerstandsmatrix

Hier ist eine solche


Widerstandsmatrix
abgebildet. Die Spalten sind
über drei Widerstände auf
Masse geführt, die Zeilen
über vier Widerstände auf
die Betriebsspannung (z.B.
5V). Der AD-Wandler-
Eingang ist noch mit einem
Folienkondensator von 1 nF
abgeblockt, da der ADC
absolut keine Hochfrequenz
mag, die da über die
Tasten, die Widerstände
und die Zuleitungen
eingestreut werden könnte.
Wird jetzt z.B. die Taste "5"
gedrückt, dann entsteht ein Spannungsteiler:

a) 1 k + 820 Ω = 1,82k nach Masse,


b) 3,3 k + 680 Ω + 180 Ω = 4,16k nach Plus.

Bei 5 Volt Betriebsspannung gelangen dann

5 * 1,82 / (1,82 + 4,16) = 1,522 Volt

an den AD-Wandler-Eingang. Rechnen wir noch 5% Toleranz


der Widerstände mit ein, dann liegt die Spannung irgendwo
zwischen 1,468 und 1,627 Volt. Der AD-Wandler macht daraus
bei 5 V Referenzspannung einen Wert zwischen 300 bis 333.
Verwenden wir nur die oberen 8 Bit des AD-Wandler-
Ergebnisses (Teilen durch vier oder Linksjustieren des
Wandlers), gibt das 74 bis 78.
Spannungswerte und Auswertung

Die anderen Kombinationen von Widerständen ergeben die in


der Tabelle gegebenen Werte für die Spannungen, die 8-Bit-
AD-Wandler-Werte und die optimale Erkennung, ob der
Spannungswert der Taste erreicht wurde.

Spannungen 8-Bit-AD-Werte Detektion


Taste
U(min.) U(typ.) U(max.) min. typ. max. (ab AD-W.)
1 0,225 0,248 0,272 11 13 14 7
2 0,396 0,434 0,474 20 22 25 18
3 0,588 0,641 0,698 29 33 36 28
4 0,930 0,969 1,048 47 49 54 42
5 1,468 1,522 1,627 74 78 84 64
6 1,959 2,020 2,139 99 103 110 91
7 2,563 2,688 2,809 130 137 144 121
8 3,285 3,396 3,500 167 173 180 156
9 3,740 3,832 3,917 190 195 201 185
* 4,170 4,237 4,298 212 216 221 207
0 4,507 4,550 4,588 229 232 235 225
# 4,671 4,700 4,726 238 240 242 237
Wie zu erkennen ist, gibt es bei der Verwendung von 5%-Widerständen und der dargestellten
Widerstandskombination keine Überlappungen der Spannungsbereiche der einzelnen Tasten.

Wer andere Widerstandskombinationen ausprobieren möchte, kann mit der zugehöigen Tabelle
herumspielen (im Open-Office-Format, im Excel-XP-Format).

Hinweise zur AD-Wandler-Hardware

ATtiny-Typen bieten meist nur die Möglichkeit, eine intern erzeugte Konstantspannung oder die
Betriebsspannung als Referenzspannung des AD-Wandlers zu wählen. Für die Tastaturschaltung
kommt nur die Betriebsspannung als Referenzspannung infrage. Diese Option ist beim Initiieren des
AD-Wandlers einzustellen.

Bei vielen ATmega-Typen kann auch eine extern erzeugte Referenzspannung verwendet werden, die
am Pin AREF zugeführt wird. Verwendet man diese Möglichkeit, wäre auch die Tastaturschaltung
aus dieser Referenz zu speisen. Verwendet man keine externe Referenzspannung, dann kommt für
den Betrieb der Tastatur nur die Möglichkeit der Verwendung der Betriebsspannung als
Referenzspannung infrage. In diesem Fall wird die Betriebsspannung per Software-Option intern an
den AREF-Pin geführt, der externe AREF-Pin wird mit einem Folienkondensator von ca.10 nF
abgeblockt.

ATmega-Typen bieten zur Erhöhung der Stabilität des AD-Wandlers ferner die Möglichkeit, diesen
über den AVCC-Pin separat zu bespeisen. Für die Tastaturschaltung alleine kann dieser Pin direkt an
die Betriebsspannung angeschlossen werden. Sollen auch noch andere Messungen veranstaltet
werden, bei denen genauer gemessen werden soll, wird der AVCC-Pin über eine Drossel von 22 µH
an die Betriebsspannung geführt und mit einem Keramikkondensator von 100 nF gegen Masse
abgeblockt.

Initiieren und Lesen des AD-Wandlers

Zum Auslesen der Tastatur wird ein AD-Wandler-Kanal gebraucht. Der AD-Wandler wird zu Beginn
eingestellt. Die beiden Beispiele zeigen den manuellen Einzelstart eines ATmega8 und den interrupt-
gesteuerten Dauerstart bei einem ATtiny13.

ATmega8: manuell starten

Als erstes Beispiel ein ATmega8, ohne Interrupts, mit manuellem Start und Stop des AD-Wandlers.
Tastatursignal am AD-Kanal ADC0.

.DEF rKey = R15 ; Register für AD-Wert


.DEF rmp = R16 ; Vielzweck-Register
; setze MUX auf Kanal 0, Linksjustieren, AREF auf AVCC
ldi rmp,(1<<REFS0)|(1<<ADLAR) ; ADMUX Kanal 0, AREF auf AVCC
out ADMUX,rmp
; AD-Wandler einschalten, Wandlung starten, Teilerrate = 128
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
; warten bis AD-Wandler fertig mit Wandlung ist
WaitAdc1:
; ADSC-Bit abfragen, wenn Null ist Wandlung fertig
sbic ADCSRA,ADSC ; conversion ready?
rjmp WaitAdc1 ; not yet
; AD-Wandler-Wert MSB lesen
in rKey,ADCH
; AD-Wandler wieder abschalten
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; switch ADC off
out ADCSRA,rmp

Man beachte, dass diese eine Wandlung 25 * 128 Takte dauert, also bei 1 MHz Prozessortakt 3,2
Millisekunden. Das macht man nur, wenn sonst nichts Wichtiges anderes zu tun ist als im Kreis
herum zu laufen.

ATtiny13: Autostart AD-Wandlung, Interrupt-gesteuert

Ja, auch ein ATtiny13 kann unsere Tastaturmatrix einlesen (das wäre mangels Pins bei der
Einzelbedrahtung gar nicht möglich).

Eine typische Routine hierfür wäre für den ATtiny13 beispielsweise die folgende Sequenz, bei der
ADC3 an Pin 2 des tiny13 im Dauerlauf (der AD-Wandler beginnt nach der Umwandlung von selbst
wieder) gestartet wird.

;
; AD-Wandler starten
;
; PB3=ADC3 wird nur für den AD-Wandler verwendet
ldi rmp,0b00001000 ; PB3 Digitaltreiber ausschalten, spart
Strom
out DIDR0,rmp
; Referenz = Betriebsspannung, Links-Justieren Ergebnis,
; ADMUX auf ADC3 stellen
ldi rmp,0b00100011 ; Referenzspannung UB, ADC3 waehlen
out ADMUX,rmp
; Autostart-Option wählen
ldi rmp,0b00000000 ; Freilauf waehlen (startet selbst)
out ADCSRB,rmp
; ADC starten, Interrupt ermöglichen, Teilerrate einstellen
ldi rmp,0b11101111 ; ADC starten, Autostart,
out ADCSRA,rmp ; Int Enable, Teiler auf 128
; fertig initiiert

Der Betrieb per Interrupt setzt voraus, dass der entsprechende Sprungvektor vorhanden ist, also z.B.

;
; Sprungvektoren fuer Reset und Interrupts, ATtiny13
;
.CSEG ; Assembliere in das Code Segment
.ORG $0000 ; an den Anfang des Code Segments
rjmp main ; Reset vector
reti ; Int0 interrupt vector
reti ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
rjmp intadc ; ADC conversion complete vector
;

Natürlich muss auch der Stapel initiiert sein und das Interrupt- Statusflag gesetzt sein (SEI).

Die Service-Routine intadc liest den AD-Wandler aus. Da Links-Justieren gesetzt ist, reicht es, das
MSB des Ergebnisses zu lesen:

;
; Interrupt Service Routine AD-Wandler
;
.DEF rKey = R15 ; Ergebnisspeicher AD-Wandler-Wert
intadc:
in rKey,ADCH ; Lese AD-Wandler MSB
reti ; Rückkehr vom Interrupt
;

Im Register rKey steht jetzt laufend aktuell der Wandlerwert des Keyboards.

Umwandeln des AD-Wandler-Werts in einen Tastencode

Die Spannung alleine ist noch nicht sehr verwendungsfähig. Da die Spannungen aufgrund der
eigenwilligen Gestaltung von Standard-Widerstandswerten (wer hat sich die Reihe 4,7 - 5,6 - 6,8 -
8,2) bloss ausgedacht? Muss entweder ziemlich sturzbetrunken oder ein Mathematiker gewesen
sein!) und der arg krummen Formel U = R1 / (R1 + R2) kommt hierfür nur eine Tabelle in Betracht.
Die Tabelle kann nicht primitiv sein, da wir ja 256 mögliche ADC-Zustände haben und keine
unnötige Platzverschwendung betreiben wollen.

Wir hangeln uns mit dem ADC-Wert in rKey durch folgende Tabelle:

KeyTable:
.DB 7, 255, 18, 1, 28, 2, 42, 3, 64, 4, 91, 5
.DB 121, 6, 156, 7, 185, 8, 207, 9, 225, 10, 237, 0, 255, 11

Das niedrige erste Byte jedes Worts sind jeweils die AD-Werte: von 0 bis <7: keine Taste gedrückt
(Tastencode=255), von 7 bis <18: Tastencode 1, etc..

Oder wer lieber gleich ASCII mag:

KeyTable:
.DB 7, 0 , 18, '1', 28, '2', 42, '3', 64, '4', 91, '5'
.DB 121, '6', 156, '7', 185, '8', 207, '9', 225, '*', 237, '0',
255, '#'

Der Code zur Auswertung sieht dann so aus:

;
; Umwandlung des AD-Werts in einen Keycode
;
GetKeyCode:
; falls der AD-Wert zwischendurch wechselt, vorher kopieren!
mov R1,rKey ; kopiere AD-Wandler-Wert nach R1
ldi ZH,HIGH(2*KeyTable) ; Z zeigt auf Tabelle
ldi ZL,LOW(2*KeyTable)
GetKeyCode1:
lpm ; Lese Wert aus Tabelle
cp R1,R0 ; vergleiche AD-Wert mit Tabellenwert
brcs GetKeyCode2 ; kleiner als Tabellenwert, Taste gefunden
inc R0 ; teste, ob am Tabellenende
breq GetKeyCode2 ; Tabellenende erreicht
adiw ZL,2 ; huepfe ein Wort weiter in der Tabelle
rjmp GetKeyCode1
GetKeyCode2:
adiw ZL,1 ; zeige auf MSB = Tastencode
lpm ; lese Tastencode aus Tabelle in R0
;

Natürlich ist jetzt noch zu prüfen, ob keine Taste gedrückt ist (R0 = 0xFF bzw. bei ASCII R0 = 0)
und es sind Anti-Prell-Aktionen zu basteln (wenn 20 mal hintereinander die gleiche Taste
herauskommt, nehme ich sie ernst, etc.).

Erfahrungen

Die Schaltung und die Software sind sehr stabil. In der ersten Version waren die Widerstände 10 mal
so groß. Das hatte höhere Störanfälligkeit zur Folge, z.B. wenn in der Nähe mit einer 2 W-Handfunke
gerade gesendet wurde.

An den Seitenanfang

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/keypad/keyboard.html1/20/2009 7:43:57 PM
Präsentation der AVR-Mikrokontroller

Pfad: Home => AVR-Tutorial

Präsentation der AVR-


Mikrokontroller mit
Anwendungsbeispielen
Die folgende Serie von Präsentationen gibt eine
Einführung in die Anwendung von AVR-
Mikrokontrollern und demonstriert an einfachen
Beispielen mit dem AVR ATtiny13 die
Verwendung der Hardware und die
Programmierung. Der Quellcode der
Anwendungsbeispiele ist zugänglich und
ausführlich kommentiert. Die Präsentation liegt
im PDF-Format vor, auf Anfrage stelle ich die
Dateien auch im OpenOffice- oder M$-Powerpoint-Format zur Verfügung.
Teil Datei Inhalt Größe
Zeigt anhand von neun praktisch gebauten Geräten die
0 Anwendungsbeispiele.pdf 763 kB
Anwendungsvielfalt von AVR-Mikrokontrollern
Erläutert den Begriff Computer, vergleicht PC,
1 Teil_1_Prozessoren.pdf Mikrocomputer und Mikrocontroller, erläutert am Beispiel 91 kB
eines Ruftonauswerters die Vorteile von Mikrokontrollern
Zahlenformate dezimal, binär, hexadezimal, Bytes, Worte,
2 Teil_2_BitsAndBytes.pdf 111 kB
Doppelworte
Rechenhardware, AVR-Typen-Übersicht, Chipformen,
3 Teil_3_Befehle.pdf 146 kB
Befehlsablauf, Instruktionen, Mnemonics
ATtiny13, Aufbau, interne Hardware, AD-Wandler,
4 Teil_4_AufbauTiny13.pdf 127 kB
Programmierinterface, eine externe Beispielbeschaltung
5a Teil_5a_UebersichtBeispiele.pdf Übersicht der Programmierbeispiele 48 kB
Ein einfaches Testboard mit dem ATtiny13, Parallelport-
Interface für die ISP-Programmierung, Programm mit Editor
5b Teil_5b_Beispiel01_02.pdf schreiben, Beispiel 01: unendliche Schleife, Assemblieren mit 329 kB
gavrasm, Assemblerausgabe, Listing, Hexdatei, Brennen mit
Pony-Prog, Beispiel 02: LED anschalten, Portausgaben
Beispiel 03: LED an- und ausschalten, Beispiel 04: LED an-
und ausschalten mit Verzögerung, DSchleifenverzögerungen,
Einführung in Timer, Taktauswahl, Vergleicher, Timer-
6 Teil_6_Beispiel03_07.pdf 650 kB
Interrupts, Beispiel 05: Timer-LED-Steuerung, Beispiel 06:
NF-Erzeugung mit Timer, Beispiel 07: Externer Interrupt,
Interrupt-Vektoren, Init Timer/Interrupt, Testaufbau
Kommandozeilen-Aufruf mit gavrasmW, Assembleraufruf
mit Batch-Datei, Beispiel 08: Tonerzeugung mit Timer und
Taster mit externem Interrupt, Beispiel 09: Tonhöen einstellen
7 Teil_7_Beispiel08_10.pdf mit Poti am AD-Wandler, Interruptvektoren, Beispiel 10: 398 kB
Morsebake, Parameter für Tonhöhe und
Gebegeschwindigkeit, Morsetabelle im Speicher, Morsetext
im Speicher,
Beispiel 11: Sinusgenerator mit AVR-Timer, Timerausgang
Rechteckgenerator und RC-Filter zur Sinus-Erzeugung, PWM-
8 Teil_8_Beispiel_11.pdf Generator mit Timer zur Sinuserzeugung, Berechnung der 245 kB
optimalen R- und C-Göße, Transistor-Emitterfolger, Aufbau,
Programm, Schirmbilder
bsp01_loop.asm
bsp02_led.asm
bsp03_blink.asm
bsp04_blink_langsam.asm
bsp04_blink_langsam_takte.asm
bsp04_blink_langsam_tn12.asm
bsp05_blink_Timer.asm 775 B
5..8 Quellcode der Beispiele ...
bsp05_blink_Timer_kurz.asm
9 kB
bsp06_lsp.asm
bsp07_keyint.asm
bsp08_morsekey.asm
bsp09_adcmorsekey.asm
bsp10_morsebake.asm
bsp11_1750_SinePwm.asm
Alle PDF-Teile zusammen plus alle Quellcode-Dateien in
0..8 praesentation.zip Unterverzeichnis (beim Auspacken Verzeichnisse entpacken 2,7 MB
lassen!)
©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/praesentation/index.html1/20/2009 7:44:09 PM
Projekt AVR Aufgabe Funktionsweise, Besonderheiten

AT90S2323 Motorzündung mit Messung der Umdrehungszahl mit zwei Sensoren,


Zünd-
ATtiny12 umdrehungsabhän- innerhalb eines bestimmten Umdrehungsbereichs
steuerung
ATtiny13 giger Vorzündung Verstellung des Zündzeitpunktes
Simulation von Messung der Drehzahl mit einem Sensor,
Motor-
ATmega8 Vorzündungsimpul- Erzeugung eines einstellbaren Vorzündsignals zur
tester
sen für Motortests Ermittlung der optimalen Vorzündverstellung
Simulation von
Erzeugen von Testsignalen zum Testen der
Motorimpulsen zur
Zündtester ATmega8 Zündsteuerung, einstellbare Drehzahl und
Prüfung der
Vorzündungsverstellung
Zündsteuerung
Messung der Anzahl Impulse oder der
Frequenz- Frequenzzähler für Impulsdauer, wahlweise Anzeige der Frequenz, der
ATmega8
zähler 0,01 Hz bis 100 MHz Pulsweite (High+Low, High, Low) in µs, der
Drehzahl in upm
Vierkanal, jeder Kanal individuell einstellbar, Akku-
Ladegerät für vier
Akkulader ATmega16 Daten gespeichert, Tastensteuerung oder seriell
Akkus
über Rechner bedienbar
Fernsteu- ATtiny12 Dreikanal- Dekodiert PCM-Fernsteuersignale, Ausgabe
erungs- Fernsteuerung und – pulsweitenmodulierter Antriebssignale für einen
auswerter ATtiny13 PWM-Ausgabe Linearkanal und Links/Rechts-Steuerung
Rufton- 1750-Hz- Ton-Bandbreite einstellbar, Ansprechzeiten
ATtiny12
auswerter Ruftonauswerter einstellbar, Haltezeiten einstellbar
DCF77- AT90S8515 DCF77-Uhr mit Synchron mit einfachem DCF77-Empfänger,
Uhr AT90S2313 LCD-Anzeige asynchron mit Quarzoszillator
Morse- Morsegenerator mit
AT9S2313 Textausgabe über die serielle Schnittstelle
generator SIO-Schnittstelle
Zündsteuerung mit AVR – Verstellung des Zündzeitpunkts
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des ATtiny13

Eine Einführung in Aufbau, Funktionsweise,


Programmierung und Nutzen von Mikroprozessoren

Teil I: Wat isse ne Mikrokontroller?


Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Wat isse ne Computer?

• Ein Computer ist eine programmgesteuerte Rechenmaschine (von eng. „to


compute“ = rechnen)
• Mechanische Rechenmaschine: fest verdrahtetes Programm =>
Rechenablauf ist durch die Mechanik festgelegt
• Computer: Der Rechenablauf wird durch das Programm bestimmt. Wechselt
das Programm, wird ein anderer Rechenablauf ausgeführt.
• Jeder Computer braucht daher:
– eine zentrale Recheneinheit (engl. „Central Processing Unit“, CPU), die Daten holt,
die Programmschritte holt (Ablaufsteuerung), rechnet und die Ein- und
Ausgabedaten verteilen kann,
– einen Programmspeicher, in dem die Rechenanweisungen (Befehle, Instruktionen)
gespeichert sind, die von der CPU abgeholt und ausgeführt werden können, und
– Ein- und Ausgabe-Einheiten (engl. „Input/Output-Units“, I/O), über die
Eingangsdaten eingelesen werden können und über die Ergebnisse (Resultate) der
verarbeiteten Daten ausgegeben werden können.
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Vergleich PC – Mikrocomputer - Mikrocontroller


• PC • Mikrocomputer • Mikro-controller
– CPU: Intel oder AMD, – CPU: Zilog etc., Takt: x –CPU: diverse, Takt: 1..20
Takt: x GHz, 32/64 Bit MHz, 8/16 Bit Busbreite MHz, 8/16 Bit Busbreite,
Busbreite = 32/64 = 8/16 Leitungen für alle intern
Leitungen für Befehlsadressen plus –Befehlsspeicher: intern x
Befehlsadressen plus 8/16 Leitungen für kB, Festspeicher
32/64 Leitungen für Daten-Kommunikation (EPROM/EEPROM),
Daten-Kommunikation – Befehlsspeicher: extern, –RAM-Speicher: intern x
– Befehlsspeicher: extern, x x kB, Festspeicher Bytes, Statisches RAM,
Gigabyte, gelesen von (EPROM), zusätzlich nicht-
externen Speichern (z.B. – RAM-Speicher: extern, x flüchtiges EEPROM x
Festplatte, CD, DVD) kB, nach Bedarf Byte
– I/O-Einheiten: Festplatten – I/O-Einheiten: parallele –I/O-Einheiten:
und andere und serielle programmierbare Pins
Speichermedien, Tastatur, Schnittstellen, nach extern
parallele und serielle Graphikschnittstelle,
Schnittstellen,
Graphikausgabe, u.v.a.m.
u.v.a.m. extern zubaubar • = Floh!
• = Maus!
• = Elefant!
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Einsatzgebiete PC, Mikrocomputer, Mikrokontroller

•PC •Mikrocomputer •Mikrokontroller


–große Datenmengen –mittlere Daten-mengen –kleine Datenmengen
–hohe Verarbeitungs- bis x MB bis x kB
geschwindigkeit –hohe Verarbeitungs- –hohe Verarbeitungs-
–intensive Anwender- geschwindigkeit geschwindigkeit
bedienung (gra- –sehr kurze –sehr kurze
phische Bedienung) Reaktionszeit auf Reaktionszeiten auf
–umfangreiche gra- Ereignisse Ereignisse
phische Darstellung –mittlere Anwender- –keine/geringe
nötig bedienung (Tastatur) Anwenderbedienung
–sehr viele verschie- –einfache graphische –einfachste gra-phische
dene Programme Darstellung nötig Darstellung (z.B. LCD)
müssen komplex –ein einziges oder –ein einziges Pro-
zusammenarbeiten wenige Programme gramm erforderlich
erforderlich
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufwand an Hard- und Software bei PC, MC und µC


•PC •MC •µC
–sehr aufwändige –aufwändige Hardware, –kaum Hardware-
Hardware, x*100 € x*10 € Aufwand, x*1 €
–Abspecken praktisch –flexibel im Aufbau –ersetzt auf einfache
kaum möglich (Stecksysteme) Weise komplizierte
–hoher Energiebedarf, –mittlerer Energie- Elektronik/Logik
x*100 W bedarf, x*10 W –speziell auf Bedarf
–hoher Verschleiß –kein Verschleiß durch abgestimmt, kein
durch Temperatur Temperatur, geringer Hardware-Ballast
und mechanische Verschleiß bei –geringster Energie-
Teile mechanischen Teilen bedarf, x*1 mW
–Betriebssystem (Stecker etc.) –kein Verschleiß
erforderlich –gering komplexe –einfachste Software,
–hochkomplexe Software, standar- genau auf Bedarf
Software disierbar zugeschnitten
–deshalb sehr hohe –daher geringe –daher kaum
Fehleranfälligkeit Fehleranfälligkeit Fehleranfälligkeit
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Beispiel Ersatz von komplizierter Elektronik:


Ruftonauswerter Analog/Mikrokontroller
•Analog •µC
–Hardware: Tonerkennung (16- –Hardware: alles in einem 8-poligen
poliges IC), Zeitverzögerung (8 IC, wenig Peripherie
bis 14 poliges IC), viel
Peripherie (Widerstände, –hochflexibel: Umbau auf andere
Kondensatoren, Potis, etc.) Frequenzen, Toleranzen und
–unflexibel: Umbau auf andere Zeiten macht nur Software-
Frequenzen, Toleranzen und Änderung erforderlich,
Zeiten macht erheblichen Umprogrammierung in weiten
Umbau erforderlich, Umbau nur Grenzen möglich
in engen Grenzen –unanfällig: kein Nachjustieren,
–anfällig: Alterung erfordert nicht spannungsabhängig
Nachjustieren,
spannungsabhängig
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Schaltbild Ruftonauswerter mit Mikrokontroller


Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufgaben Ruftonauswerter
• Erkennung: Der Ruftonauswerter überwacht einen Lautsprecherausgang auf Töne um
1750 Hz (genau: 1700 bis 1800 Hz). Bei einem reinen Ton dieser Frequenz über eine
vorwählbare Zeit (derzeit 3 Sekunden) schaltet der Ruftonauswerter das Signal für
eine bestimmte Zeit lang (derzeit 30 Sekunden) zum angeschlossenen Lautsprecher
durch.

• Manuelle Schaltung: Mit einem Taster kann das Signal dauerhaft durchgeschaltet oder
wieder auf Ruftonerkennung geschaltet werden.

• Inaktiv: Ohne Betriebsspannung des Ruftonauswerters ist das Eingangssignal


dauernd auf den Lautsprecher durchgeschaltet.

• Abschluss: Im nicht aktivierten Zustand ist der Signaleingang mit 33 Ohm


abgeschlossen.

• Zustandsanzeige: Eine grüne LED zeigt an, ob


1. kein NF-Signal vorhanden ist: 100% Intensität,
2. ein NF-Signal vorhanden ist, aber kein Rufton vorliegt: 25% Intensität,
3. ein Rufton mit Störsignalen vorliegt: 12,5% Intensität,
4. ein reiner Rufton vorliegt: 6% Intensität.

• Ausgangsanzeige: Eine rote LED zeigt bei vorhandener Betriebsspannung an, ob der
Lautsprecher abgeschaltet (LED an) oder zum Signaleingang durchgeschaltet ist (LED
aus).
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13

Eine Einführung in Aufbau, Funktionsweise, Programmierung und


Nutzen von Mikroprozessoren

Teil II: Wat iss ene Bit, Byte un Word?


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Warum Computer so gerne binär sprechen


• Lampe: an und aus,
• Schalter: geschlossen und offen,
• Logik: wahr und falsch,
• Digitallogik: low und high,
• Ladung: Minus und Plus,
• MOSFET-Kondensator/SRAM: geladen und entladen,
• Serieller Loop: Strom und kein Strom,
• Lochstreifen/Lochkarte: Loch und kein Loch,
• Digitalelektronik/SRAM: Flipflop nach links und rechts gekippt,
• Kernspeicher/Tape: magnetischer Nord- und Südpol,
• CD/DVD: verkokelt und nicht verkokelt,
• u.v.a.m.
• Ist jetzt klar, warum Computer nur 0 und 1 sprechen oder muss ich noch weiter
darüber philosophieren, wie man 10 verschiedene Abstufungen von „verkokelt“
oder „gelocht“ in Null-Komma-Nix erzeugt und erkennt?
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Dezimal-, Binär- und Hexadezimalzahlen


• Dezimalzahlen:
haben 10 Ziffern von 0..9,
bei Zahlen die größer als 9 sind, werden Stellen davor angegeben
Stellen davor sind 10, 100, 1000, ... , soviel wert wie ihre jeweilige Ziffer sagt
Kennzeichung in Assembler: Keine
• Binärzahlen:
haben 2 Ziffern: 0 und 1
bei Zahlen die größer als 1 sind, werden Stellen davor angegeben
Stellen davor sind 2, 4, 8, 16, ... , soviel wert wie ihre Ziffer sagt
Kennzeichnung in Assembler: 0b....
• Hexadezimalzahlen:
haben 16 Ziffern: von 0..9 und A..F (10..15),
bei Zahlen die größer sind als 15, werden Stellen davor angegeben
Stellen davor sind 16, 256, 4.096, 65.536, ... , mal so viel wert wie die Ziffer sagt
Kennzeichnung in Assembler: 0x... oder $..
• Alphabetimalsystem:
hat 26 Ziffern: von A..Z
bei Zahlen die größer sind als 25, werden Stellen davor angegeben
Stellen davor sind 26, 676, 17.576, 456.976, ... , mal so viel wert wie die Ziffer
sagt
Kennzeichnung in Assembler: besser nicht, wenn dann 0a...
• Das Alphabetimalsystem wird im Folgenden nicht weiter behandelt, weil
Computer einfach zu blöd sind, um das Alphabet zu kapieren.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Ähnlichkeiten zwischen Dezimal- und


Binärzahlen
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Verwandtschaft zwischen Dezimal-,


Binär- und Hexadezimalzahlen
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Bytes: acht Binärziffern


• Eine Binärzahl mit acht binären Ziffern wird ein Byte genannt.
• Der darstellbare Wertebereich liegt zwischen Null (0b00000000) und (dezimal)
255 (0b11111111). Bezeichnung: vorzeichenlose Ganzzahl, engl. „unsigned
integer byte“
• Die vier vordersten und die vier hintersten Bits können zu je einer
Hexadezimalzahlziffer zusammengefasst werden (z.B. binär 0b10110111 ist
hexadezimal 0xD7).
• Die vier vordersten Bits werden zusammen als „oberes Nibble“ und die vier
hintersten zusammen als „unteres Nibble“ bezeichnet. In einem Nibble kann
eine Dezimalziffer untergebracht werden (gepackte Binär Codierte Dezimal-
Zahlen, packed BCD), die Zustände A bis F sind dann verboten. Unteres und
oberes Nibble eines Bytes können z.B. mit der Instruktion SWAP vertauscht
werden. Beispiel in Assemblersprache:
; Oberes und unteres Nibble in Register R16 vertauschen
swap R16 ; tausche oberste und unterste vier Bits gegeneinander aus
• Wird das vorderste Bit nicht als Binärziffer, sondern als Vorzeichen-Bit
interpretiert (bei negativen Zahlen ist das vorderste Bit gleich Eins), steht der
Wertebereich von –128 (0b11111111) über 0 (0b00000000) bis +127
(0b01111111) zur Verfügung. Bezeichnung: vorzeichenbehaftete Ganzzahl,
engl. „signed integer byte“.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Bytes in 8-Bit-Prozessoren
• Alle 8-Bit-Prozessoren verarbeiten 8 Bits gleichzeitig!
• Die Recheneinheit kann jeweils 8 Bit eines Registers (R0..R31) mit jeweils 8 Bit
eines zweiten Registers (R0..R31) oder einer Konstanten (0..255) behandeln
und speichert das 8 Bit breite Ergebnis in einem Register (R0..R31).
Z.B. in Assemblersprache:
; Addiere R1 und R0, speichere Ergebnis in R1
add R1,R0 ; Zeitbedarf: 1 Takt, @4MHz: 0,25 µs
• Überschreitet eine Operation (z.B. eine Addition oder Subtraktion) den
zulässigen Wertebereich nach oben hin (Ergebnis ist größer als dezimal 255)
oder nach unten hin (Ergebnis kleiner als Null), wird ein Status-Bit (engl. „flag“)
gesetzt (Carry-Bit, C). Ist das Ergebnis Null, wird das Status-Bit Z gesetzt (Zero).
Die Status-Bits können in Sprungbefehlen abgefragt und dazu benutzt werden,
die Verarbeitung in verschiedenen Programmteilen fortzusetzen (bedingte
Sprünge, engl. „conditional branch“).
Z.B. in Assemblersprache:
; Subtrahiere R1 und R0
sub R1,R0 ; ziehe R0 von R1 ab, Ergebnis in R1
breq gleich ; Ergebnis war Null, springe nach gleich:
brcs kleiner ; Ergebnis kleiner Null, springe nach kleiner:
... ; Ergebnis war größer Null, mache weiter
gleich:
... ; Ergebnis war gleich, mache was anderes
kleiner:
... ; Ergebnis war kleiner, mache ganz was anderes
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Hast Du da noch Worte?


• 16 Bit breite Binärzahlen werden als Worte (eng. word) bezeichnet.
• Der Wertebereich reicht von 0 bis 65.535 (unsigned integer word).
• Jeweils vier Bits eines Wortes können als Hexadezimalziffer zusammengefasst
werden (z.B. 0b1001.0101.1110.1010 ist gleich 0x95EA).
• Das obere Byte eines 16-Bit-Wortes wird als höherwertiges Byte oder „most
significant byte“ (MSB), das untere Byte als niederwertiges Byte oder „least
significant byte“ (LSB) bezeichnet.
• Wird das vorderste Bit als Vorzeichen interpretiert, reicht der Wertebereich von –
32768 bis +32767 (signed integer word).
• 8-Bit-Prozessoren können auch 16-Bit-Zahlen verarbeiten. Dazu werden zwei 8-
Bit-Register nacheinander verarbeitet. Im Prinzip können Paare aus beliebigen
Registern gebildet werden, z.B. R5:R6 (R5 ist dann MSB, R6 ist LSB, „:“
signalisiert den Zusammenhang beider) und nacheinander behandelt werden.
• Einige Instruktionen erlauben die direkte Verarbeitung bestimmter
Doppelregister. Bei den AVR sind dies die drei Registerpaare R27:26, R29:R28,
R31:R30, sie werden als X (XH:XL), Y (YH:YL) und Z (ZH:ZL) bezeichnet. In
sehr eingeschränktem Umfang ist auch R25:R24 für bestimmte Operationen
zulässig, das Paar hat keinen eigenen Namen. Beispiele in Assembler:
adiw R24,1 ; erhöhe Wort R25:R24 um Eins
sbiw XL,5 ; erniedrige Wort X um fünf
movw ZL,XL ; kopiere Inhalt von XH:XL nach ZH:ZL
st Z+,R0 ; kopiere Inhalt von Register R0 zur Speicheradresse in Z und erhöhe die Adresse um Eins
ldd R16,Y+14 ; kopiere den Inhalt der Speicherzelle, auf die Y+14 zeigt, in das Register R16
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Wo braucht man so was?


• Beispiel Frequenzzähler:
• Eingangsfrequenz für die Messung: max. 20 MHz (50 ns)
• Messdauer: 0,25 Sekunden
• Zählung mit eingebautem 8-Bit-Counter: Überlauf des Zählers alle 256*50 ns =
12,8 µs
• Zählung der Zählerüberläufe, maximale Anzahl = 20.000.000 / 4 / 256 = 19.531
• Anzahl Überläufe ist größer als 255 (Fassungsvermögen 1 Byte), nicht größer
als 65.535 (Fassungsvermögen 2 Bytes), benötigt zwei Bytes für Überläufe
• Zusammen mit 1 Byte letzter Zählerstand: 3 Byte lange Zahl
Speicherung z.B. in R3:R2:R1
• Multiplikation der Zahl mit 4 ergibt Frequenz in Hz, kann dabei ein Überlauf
auftreten?
20.000.000 ist hexadezimal 0x01.31.2D.00, benötigt also vier Bytes!
• Beispiel für Multiplikation mit vier in Assembler:
; R3:R2:R1 mit vier multiplizieren = Binärziffern zwei Mal links schieben
clr R4 ; wird wegen Überlauf gebraucht, Null setzen
lsl R1 ; niedrigstes Byte links schieben, Überlauf in Carry
rol R2 ; zweites Byte links rotieren, Carry einschieben
rol R3 ; drittes Byte links rotieren, Carry einschieben
rol R4 ; allerhöchstes Byte links rotieren, Carry einschieben
lsl R1 ; niedrigstes Byte noch mal links schieben
rol R2 ; zweites Byte noch mal links rotieren
rol R3 ; drittes Byte noch mal links rotieren
rol R4 ; viertes Byte noch mal links rotieren, und fertig
; Zeitbedarf: 9 Takte, bei 4 MHz Taktfrequenz: 2,25 µs
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Darf‘s ein bisschen mehr sein?


• Zahlen können fast beliebig groß sein. Dazu werden drei oder mehr Register
zusammengefasst und als eine Zahl interpretiert und verarbeitet.
• Drei Bytes (z.B. R2:R1:R0) ergeben dann einen Wertebereich von 0 bis
16.777.215, vier Bytes (z.B. R15:R14:R13:R12) einen Wertebereich bis
4.294.967.295, usw.
• Die Verarbeitung solcher Zahlen (z.B. Erhöhen, Erniedrigen, Addition,
Subtraktion) erfolgt dann Byte für Byte in einzelnen Schritten, wobei das
Übertragsbit Carry C für Überträge aus niedrigeren Bytes und das Zerobit Z mit
verwendet werden.
• Beispiel in Assemblersprache:
; Erhöhen von R32:R1:R0 um Eins
inc R0 ; erhöhe niedrigstes Byte um Eins
brne fertig ; wenn kein Überlauf zu Null springe nach fertig
inc R1 ; Überlauf, erhöhe nächsthöheres Byte um Eins
brne fertig ; wenn kein Überlauf zu Null springe nach fertig
inc R2 ; Überlauf, erhöhe höchstes Byte um Eins
fertig: ; hier landen alle Fälle letztendlich
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Schlussfolgerungen
• Es gibt beliebig viele Zahlensysteme, und man wundert sich, weshalb unsere
Vorfahren ausgerechnet das Zehnersystem ausgewählt haben und nicht das
Zweier-, Dreier-, Vierer-, Siebener-, Zwölfer-, Sechsundzwanziger- oder
Sechziger-System. Wo wir doch zwei Füsse und zwei Hände haben (= vier), das
Bier im Sixpack handhaben (=6), der Sieben eine gewisse Magie zugeschrieben
wird (=7), ein Bierkasten 12 Flaschen fasst (=12), das Sechsundzwanziger-
System mit dem Alphabet abzuwickeln wäre (Ziffern wären überflüssig) und
Zahlen im 60-er System so schön kurz sind. Tradition ist manchmal arg
ineffektiv.
• Computer sprechen binär, manchmal nibbelig und eher nebenbei etwas
hexadezimal, keinesfalls aber dezimal!
• Die Zahlenumwandlung in binär/hexadezimal ist für‘s Denken etwas mühsam,
aber aus Computersicht höchst effektiv!
• Auch im kleinsten Mikrokontroller lassen sich noch größte Zahlen mühelos
verarbeiten!
• Für‘s Handling von 32- und 64-Bit-Zahlen braucht es keinen High-End-PC, es
reicht ein 8-beiniges Mikrokontrollerchen!
• So eine Multiplikation mit vier geht auch bei nur 4 MHz Takt noch sauschnell.
• GHz-CPU-Takt ist dagegen total out, weil der PC mehr mit Fensterln und Platten
beschäftigt ist als mit Rechnen!
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des ATtiny13

Eine Einführung in Aufbau, Funktionsweise, Programmierung


und Nutzen von Mikroprozessoren

Teil III: Wat macht ene


Mikrokontroller?
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Interner Aufbau eines Mikrokontrollers

Takt-
steuerung

Programm- Daten-
speicher speicher
CPU
und
Register

Diverse Ein- und


interne Ausgabe-
Hardware pins
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Typen und Eigenschaften von ATMEL AVR


Device Flash EEPROM SRAM I/O F.max Ub 16-bit 8-bit PWM UART A/D Ana Interrupts Pin
kB Byte Byte Pins MHz V Timer Timer 10-Bit Comp rupts Dip
ATtiny12 1 64 -- 6 8 1.8-5.5 -- 1 -- -- -- Yes 5 8
ATtiny13 1 64 64 6 20 1.8-5.5 -- 1 2 -- 4 Yes 9 8
ATtiny15L 1 64 -- 6 1,6 2.7-5.5 -- 2 1 -- 4 Yes 8 8
ATtiny25 2 128 128 6 20 1.8-5.5 -- 2 4 -- 4 Yes 15 20
ATtiny26 2 128 128 16 16 2.7-5.5 -- 2 2 -- 11 Yes 11 32
ATtiny28L 2 -- 32 11 4 1.8-5.5 -- 1 -- -- -- Yes 5 28
ATtiny45 4 256 256 6 20 1.8-5.5 -- 2 4 -- 4 Yes 15 20
ATtiny85 8 512 512 6 20 1.8-5.5 -- 2 4 -- 4 Yes 15 20
ATtiny2313 2 128 128 18 20 1.8-5.5 1 1 4 1 -- Yes 8 20
ATmega8 8 512 1024 23 16 2.7-5.5 1 2 3 1 8 Yes 18 28
ATmega128 128 4096 4096 53 16 2.7-5.5 2 2 8 2 8 Yes 34 64
ATmega16 16 512 1024 32 16 2.7-5.5 1 2 4 1 8 Yes 20 40
ATmega162 16 512 1024 35 16 1.8-5.5 2 2 6 2 -- Yes 28 40
ATmega164 16 512 1024 32 20 1.8-5.5 1 2 6 2 8 Yes 31 40
ATmega165 16 512 1024 54 16 1.8-5.5 1 2 4 1 8 Yes 23 64
ATmega168 16 512 1024 23 20 1.8-5.5 1 2 6 1 8 Yes 26 28
ATmega169 16 512 1024 53 16 1.8-5.5 1 2 4 1 8 Yes 23 64
ATmega2560 256 4096 8192 86 16 1.8-5.5 4 2 16 4 16 Yes 57 100
ATmega32 32 1024 2048 32 16 2.7-5.5 1 2 4 1 8 Yes 19 40
ATmega406 40 512 2048 18 1 1.4-5,5 1 1 1 -- -- Yes 23 48
ATmega48 4 256 512 23 20 1.8-5.5 1 2 6 1 8 Yes 26 32
ATmega64 64 2048 4096 53 16 2.7-5.5 2 2 8 2 8 Yes 34 64
ATmega649 64 2048 4096 53 16 1.8-5.5 1 2 4 1 8 Yes 25 64
ATmega88 8 512 1024 23 20 1.8-5.5 1 2 6 1 8 Yes 26 32
ATmega8515 8 512 512 35 16 2.7-5.5 1 1 3 1 -- -- 16 40
ATmega8535 8 512 512 32 16 2.7-5.5 1 2 4 1 8 Yes 20 40

Liste ist im Original doppelt so lang! Da ist für jeden was dabei!
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Typenvergleich
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Befehlsablauf
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Befehlsablauf im Einzelnen
• __________ __________ _______
• Taktsignal: ____| |__________| |________| |_

• Befehl bearbeiten: | Programmzähler an Programmspeicher ausgeben


| Befehlswort aus Programmspeicher auslesen
| Befehlswort dekodieren
| Befehl ADD ausführen
| Ergebnis speichern
Fertig |

• Befehl braucht zwei Takte zur Bearbeitung: Takt 1 liest aus


Programmspeicher, Takt 2 führt den Befehl aus, @4 MHz: 0,5 µs pro Befehl
• Pre-Fetch bei ATMEL-AVRs:
Während der Ausführung des vorausgehenden Befehls wird bereits der
nächste Befehl geholt; falls kein Sprung erfolgt, kann der nächste Befehl
direkt bearbeitet werden; Konsequenzen: doppelte Ausführungs-
geschwindigkeit, @4 MHz: 0,25 µs pro Befehl, Befehle ohne Sprung
brauchen nur einen Takt, mit Sprung zwei Takte
• Der Zeitbedarf für jeden Befehl ist exakt vorhersehbar
• Alle Abläufe lassen sich exakt zeitlich planen und ausführen
• Im PC nahezu unmöglich, da Multitasking-Betriebssysteme darüber
entscheiden, welches Programm wann wieviel Zeit bekommt!
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Befehle, Instruktionen (Assembler Mnemomonic)


• Die wichtigsten Befehle/Instruktionen beim ATtiny13
–Rechnen: Addieren (Add, Adc) und Subtrahieren (Sub, Sbc) ohne und mit Übertrag,
Vergleichen mit Konstante (Cpi) / Register (Cp) / Register und Übertrag (Cpc), Um eins
erhöhen (Inc) oder vermindern (Dec), Logisches Und (And) / Oder (Or) / Exklusiv-Oder (Eor),
Bits auf 0 (Cbr) oder 1 (Sbr) setzen, Register auf Festwert setzen (Ldi) / auf Null setzen (Clr)
/ auf 255 (Ser) setzen
–Bit und Bit-Test: Bit im Port auf Eins (Sbi) oder Null (Cbi) setzen, Logisches Links-
Schieben (Lsl) oder Rechtsschieben (Lsr), Links- (Rol) oder Rechts- (Ror) Schieben über
Carry, Arithmetisches Rechtsschieben (Asr), Unteres und oberes Nibble tauschen (Swap),
Flaggbit setzen (Set) / rücksetzen (Clt) / auf Registerbit setzen (Bst) / in Register laden (Bld),
Flags im Statusregister setzen (Sex) oder löschen (Clx) mit x={Z,C,N,V,S,H,T,I}, Einer-
(Com) und Zweier-(Neg) Komplement
–Sprünge: Relativer (Rjmp) / Indirekter (Ijmp) Sprung, Relativer (Rcall) / Indirekter (Icall)
Unterprogrammaufruf, Relativsprung bei gesetztem (Brxs) / gelöschtem (Brxc) Statusbit mit
x={Z,C,N,V,S,H,T,I}, Überspringen bei gesetztem (Sbxs) oder gelöschtem (Sbxc) Bit mit {x=r
Register, x=i I/O-Port)
–Datentransfer: Register zu Register (Mov), Registerwort zu Registerwort (Movw),
Speicher zu Register direkt (Ld) / indirekt (Ldd) / Festadresse (Lds), Register in Speicher
direkt (St) / indirekt (Std) / Festadresse (Sts), Programmspeicher in Register (Lpm), Register
in I/O-Port (Out), I/O-Port in Register (In), Register auf Stapel (Push) und vom Stapel (Pop)
– CPU-Kontrolle: Nichtstun (Nop), Schlafen (Sleep), Wachhund rücksetzen (Wdr), Debug-
Unterbrechung (Break)
• Jeder Befehl belegt ein Wort (=2 Byte) im Programmspeicher.
• Die meisten Instruktionen benötigen einen einzigen Takt für die Ausführung,
Sprungbefehle zwei Takte.
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Zusammenfassung
• Beim Abarbeiten von Befehlen/Instruktionen im Mikrokontroller geht es
streng geordnet und überaus berechenbar zu.
• Scheffe ist CPU; Hoflieferant der Programmspeicher; Höflinge mit Vitamin B
und direktem Zugang zum Chef sind die 32 Register; Indianer sind die
Speicher und diverse interne Gerätschaften. Für die Außenpolitik sorgen
externe Pins, die geruhen, etwas ein- oder auszugeben.
• Alle Befehle/Instruktionen werden nacheinander bearbeitet (konsekutiv), ein
Nebeneinander verschiedener Aufgaben kann und darf es auch nicht geben.
• Den Takt der Verarbeitungsmusik gibt der Taktgeber vor, die aktuelle
Bearbeitungsadresse steht immer im Programmzähler (program counter).
• Nach außen hin herrscht absolute Ruhe! Kein Pin gibt interne Adressen oder
Daten nach außen, es sei denn, es wird so angewiesen! Unterschied zu PC
und MC!
• AVRs holen schon mal den nächsten Befehl, während sie den letzten noch
gar nicht richtig bearbeitet haben (Pre-Fetch).
• Wildes Umherspringen im Programmablauf wird deshalb mit Strafzeiten von
mindestens einer Taktlänge geahndet.
• Es gibt mehr als 100 verschiedene Befehle, die alle was anderes bewirken.
Kein Mensch kann die auswendig lernen und sich merken, was die anstellen,
wie lange sie brauchen, welche Flaggen sie wann setzen oder in Ruhe
lassen. Für vergessliche Menschen gibt es das vollständige Instruction Set
Summary am Ende jedes Datenblattes, für umme bei http://www.atmel.com,
Microprozessors, 8-Bit-RISC. Da steht alles drin.
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Programmierung von
ATMEL AVR
Mikroprozessoren am
Beispiel des ATtiny13
Eine Einführung in Aufbau,
Funktionsweise, Programmierung
und Nutzen von Mikroprozessoren

Teil IV: Wat iss ene ATtiny13?


Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Pin-Out des ATtiny13


• Betriebsspannungsanschlüsse festgelegt (Pins 4
und 8; 1,8 bis 5,5 V Betriebsspannung)
• Je nach Programmierung haben die anderen Pins
unterschiedliche Funktionen:
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufbau des ATtiny13 - Prozessor

• Zentraleinheit:
– 32 Arbeitsregister zu je 8 Bits, R0..R31
– 120 Instruktionen (Rechnen, Sprünge,
Bitmanipulation, Datentransfer, Kontroll-
Funktionen)
• Speicher
– 512 Worte Programmspeicher (Flash-
EEPROM)
– 64 Byte nichtflüchtiger EEPROM-Speicher
– 64 Byte flüchtiger Statischer RAM-Speicher
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufbau des ATtiny13 – Taktgenerator –


8-Bit-Zähler
• Taktgenerator:
– Interner Taktgenerator 9,6 MHz, Auto-Kalibrierung werksseitig,
programmierbarer Vorteiler durch 1..256 (ergibt 9,6 MHz bis 37,5
kHz Taktfrequenz)
– Externer (Quarz-)Oszillator zuschaltbar an Pin 2 (PB3)
• Ein 8-Bit-Timer/Zähler:
– Quelle der Zählimpulse: Timer = vom Taktoszillator über
Vorteiler durch 1/8/64/256/1024, Zähler = Taktung durch
ansteigende oder abfallende Signale am T0-Pin
– 2 Vergleichsregister für Pulsweiten-Generatoren (PWM-Modi)
– Programmierbare Zählweite (1..256) im CTC-Modus
– Zwei Ausgabe-Pins (OC0A, OC0B) programmierbar für externe
Hardware-Signale (für Signalgeneratoren etc.)
– Drei Unterbrechungskanäle (Interrupt-Vektoren: Überlauf,
Vergleich A, Vergleich B) für halbautomatische Abläufe
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufbau des ATtiny13 – I/O-Pins,


Analogvergleicher
• max. 6 Ein-/Ausgabe-Pins (I/O-Pins):
– Richtung manipulierbar (Ein- oder Ausgang)
– bei Eingängen sind Pull-Up-Widerstände zuschaltbar
– Unterbrechung (Interrupt) bei Eingang INT0 (PB1)
programmierbar (Int bei fallender oder steigender
Flanke oder bei Nullpegel)
– Unterbrechung (Interrupt) bei Pegelwechsel bei allen
Pins wählbar, mit Maskierung der auslösenden Pins)
• Analog-Vergleicher
– zuschaltbarer Analogvergleich an den Pins AIN0 und
AIN1 (PB0 und PB1)
– Unterbrechung (Interrupt) bei Wechsel
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufbau des ATtiny13 –


A/D-Wandler

• Vier-Kanal AD-Wandler:
– 10 Bit Auflösung (= 1 Promille Genauigkeit)
– Interne Spannungsreferenz 1,1 V oder
Betriebsspannung als Spannungsreferenz
– Interner Wandlerteiler 2..128 aus Prozessortakt
– 7 Quellen für automatische Triggerung
(dauernd, Analogvergleicher, INT0-Pin,
Timer/Counter Überlauf oder Vergleicher,
Pegelwechsel an I/O-Pin)
– Interrupt bei Wandlungsende programmierbar
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Aufbau des ATtiny13 – Serielle


Programmierung
• Serielles Programmierinterface:
– Programmierung in der Schaltung möglich (ISP
= In-System-Programming),
– PB0, 1 und 2 sowie Reset und die zwei
Betriebsspannungsanschlüsse wechseln beim
Programmieren automatisch ihre Funktion und
Richtung (einfach 6-Pin oder 10-Pin-
Programmier-Stecker anstecken)
– Wahl zwischen Hochspannungs- und
Niederspannungsprogrammierung möglich (im
Hochspannungsmodus 12V am Reset-Eingang,
besondere Einstellungen zugänglich)
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Beispiel für eine Anwendung: Morsebake


Features:
-Wählbarer Text, mit allen Sonderzeichen
-Einstellbare Gebegeschwindigkeit von 5 bis 500 bpm
-Wählbare Tonhöhe von 300 bis 8000 Hz
-Absolut exaktes Timing „nach Lehrbuch“
-Auszug aus der Software:
; **************************************************************
; * Angeschlossener Taster startet Morseausgabe eines Texts *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | | ___
; |PB3 PB2|--|___|--|<|--O + 5 Volt
; / 3| |6 _ LED
; 0 Volt O--O O--|PB4 PB1|---|_|--O + 5 Volt
; 4| | / \
; 0 Volt O----|Gnd PB0| ---
; |__________| LSP
Aufbau und Programmierung von Mikroprozessoren am Beispiel des ATtiny13 – ©2005 by http://www.avr-asm-tutorial.net

Zusammenfassung
• Die Innereien eines ATtiny13 hätten vor 15 Jahren eine Z80-Kiste mit
mindestens 19 Zoll, drei Höheneinheiten sowie 10 bis 15 Europa-
Steckkarten im Format 160*100 samt 64-poligem Bussystem und
lüftergekühltem Netzteil gefüllt.
• Ein Tiny13 ist für schlappe 2 € bei Ebay zu kriegen, wieviel würde die
obige Kiste kosten? (Schon das Gehäuse von Isel kostet locker das 50-
fache.)
• Mit einem Strombedarf von maximal 10 mA (bei 5 V und 9,6 MHz Takt,
ohne Schlafmodus) kann die ganze Maschinerie aus einer Batterie
gespeist werden. Für den Saft einer einzigen Intel-4GHz-CPU kann
man deutlich mehr als 1000 von diesen Tiny‘s gleichzeitig betrieben.
• Ein doch recht komplexes Gerät wie eine Morsebake schrumpft vom
TTL/CMOS-Grab-Niveau zu einem achtpoligen Etwas, dessen Sockel
noch den größten Raum einnimmt. Robert macht‘s mit SOIC-
Fliegenschiss-Gehäuse und Mikroskop noch um den Faktor 20 kleiner
und es passt zusammen mit dem Akku in einen Fingerhut.
• Die Intellenz steckt nur noch im Programm und nicht mehr in der
Hardware.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13

Eine Einführung in Aufbau, Funktionsweise, Programmierung


und Nutzen von Mikroprozessoren

Teil 5a: Übersicht über die Programmierbeispiele


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Übersicht über die


Programmierbeispiele I
• Beispiel 01: Unendliche Schleife
– Schreiben eines Programms mit Texteditor
– Übersetzen in Maschinensprache
– Einprogrammieren in den Flash-Speicher des Tiny13
– Unendliche Schleife
• Beispiel 02: Ausgang und LED-Treiber
– Einen I/O-Pin als Ausgang definieren und auf Null setzen
– Eine LED an diesem Ausgang antreiben
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Übersicht über die


Programmierbeispiele II
• Beispiel 03: Ausgang aus- und einschalten, schnell
– Schleife mit Ein- und Ausschalten eines I/O-Pins
• Beispiel 04: LED langsam An und Aus
– Ein- und Ausschalten mit Verzögerungsschleife
– Herunterzählen eines Zählers und bedingte Sprünge
– Ausführungszeiten für Instruktionen
• Beispiel 05: Timer schaltet LED
– Programmieren des Timers als selbstständiger Ein- und Ausschalter
• Beispiel 06: Timer macht Töne
– Schnelles Ein- und Ausschalten als Tongenerator
• Beispiel 07: Taster schaltet LED ein
– Nutzung eines I/O-Pins als Interruptquelle zum Schalten
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Übersicht über die


Programmierbeispiele III
• Beispiel 08: Morsegenerator
– Interrupt-gesteuertes Schalten eines NF-Tongenerators mit Timer mittels
Taster
• Beispiel 09: Tonhöhen-Einstellung mit AD-Wandler
– Spannungsmessung mit AD-Wandler und Tonhöhenverstellung beim
Morsegenerator
• Beispiel 10: Morseausgabe eines Texts
– Interrupt-gesteuerte komplexe Abläufe
– Ausgabe eines Bakentextes mit Morsegenerator
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13

Eine Einführung in Aufbau, Funktionsweise, Programmierung und


Nutzen von Mikroprozessoren

Teil IV: Programmieren an Beispielen


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Die Test-Hardware
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Das Parallelport-Interface
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Testhardware
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Überblick: Programmieren für Anfänger

1. Schreiben des Programmcodes mit einem Editor


ergibt eine Textdatei
2. Übersetzen des Programmcodes mit einem Assembler
ergibt ein Programmlisting und eine Hexdatei mit den
Maschinenbefehlen
3. Einlesen der Hexdatei und Einbrennen der
Maschinenbefehle in den Programmspeicher mittels eines
Brennprogramms und eines Programmier-Interfaces
4. AVR startet neu und führt die Maschinenbefehle aus
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierbeispiel 01: Die unendliche Schleife


Man nehme: einen Editor (z.B. M$: Notepad, Linux: KEdit) und tippe ein:

• Zeilen mit einem Semikolon werden von da an ignoriert (Kommentare)


• „loop:“ ist eine Sprungmarke (engl. Label), es dient der Kennzeichnung
für den Assembler, Benennung beliebig, immer Doppelpunkt am Ende
• „rjmp“ ist eine Instruktion, sie erzeugt beim Übersetzen ein Befehlswort
• „rjmp loop“ bewirkt, dass der Prozessor um einen Befehl rückwärts
springt (unbedingter Sprung)
• Das macht er (und nichts anderes), solange er unter Spannung steht
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Übersetzen des Programms mit gavrasm


• Man nehme: einen Assembler (wie z.B. meinen eigenen, genannt gavrasm)
• Man öffne: ein Befehlszeilenfenster (M$: Eingabeaufforderung, Linux: bash) und
tippe ein (Pfade natürlich entsprechend der eigenen Pfade):

• Dann wird der Assembler aufgerufen mit:

• „Pfad\gavrasm“ ruft den Assembler auf, „beispiel01[.asm]“ ist die Quelldatei


• -seb bedeutet: s=erzeuge eine Symbolliste, e=gib erweiterte Errormeldungen
aus, b=gib Kommentare für Beginner aus
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Hier spricht der Assembler


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Was will er uns sagen?


• Dabei bedeutet:
• „gavrasm gerd's AVR assembler Version 1.4 (C)2005 by DG4FAC“: die Version
des Assemblers
• „Kompiliere Quelldatei: beispiel01.asm“: die assemblierte Textdatei
• „Durchgang: 1, 5 Zeilen verarbeitet.“: der Assembler hat alle Instruktionen
verstanden, kein Fehler ist aufgetreten.
• „Durchgang: 2, 5 Zeilen verarbeitet.“: der Assembler hat beim zweiten
Durchgang auch alle Sprungmarken, Konstanten und Definitionen komplett
verstanden und gefunden.
• „Warnung 006: Keine DEVICE-Direktive, keine Typprüfung!“: es wurde kein
spezifischer AVR-Typ mit der DEVICE-Direktive festgelegt, deshalb wurde nicht
überprüft, ob die verwendeten Instruktionen bei diesem AVR-Typ zulässig sind.
• „1 Worte Code, 0 Worte Konstanten, Gesamt=1 = 0,0%“: Es wurde eine 16-Bit-
Instruktion (ein Befehlswort) erzeugt, im Programm werden keine Tabellen mit
Konstanten verwendet, und insgesamt ist der verfügbare Flash-Speicher zu 0,0%
durch den Code belegt.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Wer‘s schriftlich lieber mag ...


• In dem Verzeichnis befinden sich jetzt zwei neue Dateien:
„beispiel01.lst“ und „beispiel01.hex“.
• beispiel01.lst“: Das Listing beim Übersetzen:
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Kryptisch: Maschinencode in Hex


• Der einzige Maschinenbefehl an Adresse 000000 lautet also „CFFF“
• Die Hex-Datei enthält die Maschinenbefehle in folgendem Format:

• Diese Datei enthält alle nötigen Daten für die Programmierung in den
Flash-Speicher des Chips plus Adressangaben und Prüfbytes.
• Sie wird vom Brennprogramm eingelesen, ausgewertet und der
enthaltene Maschinencode (hier: CFFF) in den Flash-Speicher
übertragen.
• Als Beispiel für ein Brennprogramm wird PonyProg2000 verwendet.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Burn it in ...
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 02: Die Test-Hardware


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 02: LED an


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 02: LED an, Programmschritte


• „.INCLUDE „tn13def.inc““:
Liest die Prozessor-spezifischen Definitionen des ATtiny13 ein (zulässige
Instruktionen, Nummern der I/O-Ports, spezielle Labels, etc.)

• „sbi DDRB,1“:
setze das Bit 1 im Datenrichtungsregister von Port B auf Eins, das macht
dieses Portbit (PB1, Pin 6) zu einem Ausgang.

• „cbi PORTB,1“:
setze das Portbit PB1 auf Null, der Ausgang wird damit auf Null Volt
gezogen und die LED zieht aus der Versorgungsspannung über den
Widerstand Strom und leuchtet.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13

Eine Einführung in Aufbau, Funktionsweise, Programmierung


und Nutzen von Mikroprozessoren

Teil VI: Programmieren an weiteren Beispielen


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierbeispiel 03:
LED an und ausschalten
•„sbi DDRB,1“ schaltet
Richtungsregister von Pin 6 auf
Ausgang
•„cbi PORTB,1“ schaltet Ausgang auf
Null, die LED leuchtet
•„sbi PORTB,1“ schaltet Ausgang auf
Eins, die LED leuchtet nicht
•„rjmp loop“ springt wieder zurück du
beginnt beim zweiten Befehl neu

•„cbi“ und „sbi“ brauchen je einen Takt,


„rjmp“ braucht zwei Takte, macht
zusammen vier Takte

•1,2 MHz interner Takt durch vier ergibt


eine Schaltfrequenz von
300 kHz
•Da ist beim besten Willen das An und
Aus der LED nicht mehr zu erkennen.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierbeispiel 04:
LED an und aus mit Verzögerung
•„sbi DDRB,1“ schaltet Richtungsregister von Pin 6
auf Ausgang
•„sbi PORTB,1“ schaltet Ausgang auf Eins, die LED
ist aus
•„sbiw ZL,1“, „brne loop1“ zieht vom Inhalt des
Registerpaars ZH:ZL so lange eins ab, bis es Null
wird, das wiederholt sich 65535 mal
•cbi PORTB,1“ schaltet Ausgang auf Null, die LED
ist an
•„sbiw ZL,1“, „brne loop1“ zieht vom Inhalt des
Registerpaars ZH:ZL so lange eins ab, bis es Null
wird, das wiederholt sich 65535 mal
•„rjmp loop“ springt wieder zurück und beginnt
beim zweiten Befehl neu

•„cbi“ und „sbi“ brauchen je einen Takt, „rjmp“


braucht zwei Takte, die beiden Verzögerungs-
schleifen brauchen zusammen 65535*4*2 =
524.280 Takte, macht zusammen 524.284 Takte

•1,2 MHz interner Takt durch 524.284 ergibt eine


LED-Schaltfrequenz von
2,29 Hz
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Nachteile der Schleifenverzögerung


• Die CPU wird fast ausschließlich mit Unsinn beschäftigt (Abziehen, Prüfen,
Rücksprung)
• Die CPU kann nichts anderes tun als die Schleife zu bearbeiten, sonst
würde sich das Schleifen-Timing und die LED-Frequenz drastisch ändern
• Die CPU verbraucht unnötig viel Strom für das Lesen aus dem
Programmspeicher und das Zählen in der Schleife

Daher:
• Verzögerungen besser mit dem eingebauten Timer.
• Möglichkeiten der Hardware soweit als möglich ausschöpfen.
• CPU schlafen legen, verbraucht dann nur noch wenig Strom.
• Timer läuft unabhängig von CPU, die kann währenddessen was
anderes tun oder eben die meiste Zeit schlafen, bis es wieder Arbeit
gibt.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Funktionsweise von Timer/Countern


• Ein Timer ist ein Binärzähler, der von einem festen Zeittakt angetrieben
wird.
• Der fester Zeittakt kann mittels eines programmierbaren Vorteilers (engl.
Prescaler) vom Prozessortakt abgeleitet werden.
• Dient als Taktgeber das Signal an einem externen Pin, heißt der Timer
Counter.
• Die Taktquelle, die den Timer/Counter antreibt, wird durch Schreiben eines
Kontrollbytes an einen bestimmten I/O-Port ausgewählt. Der Zähler kann
damit auch jederzeit von der CPU angehalten werden.
• Der Stand des Timers/Counters kann von der CPU aus jederzeit gelesen
und beschrieben werden.
• Ein Überlaufen des Zählers kann für eine Unterbrechungsanforderung an
die CPU verwendet werden (Timer Overflow Interrupt).
• Um die CPU von der Aufgabe zu entlasten, den Zählerstand laufend zu
überwachen, sind an den Timer eine oder mehrere Vergleicher
angegliedert. Sie vergleichen den Zählerstand mit einem programmierten
Wert im Compare-Register und lösen bei Gleichheit (Compare Match)
voreingestellte Ereignisse aus, wie z.B.:
- Unterbrechungsanforderung an die CPU (Compare Match Interrupt),
- Null-Setzen, Eins-Setzen oder Umkehr an einem externen Pin,
- Rücksetzen des Timers auf Null.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Aufbau des 8-Bit-Timers - Taktauswahl


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Aufbau des 8-Bit-Timers - Vergleicher


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Aufbau des 8-Bit-Timers - Interrupts


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 05: Timer steuert LED


Zuerst wird der interne Vorteiler für
den Prozessortakt auf 32 gesetzt.
Dadurch läuft die CPU langsamer.
Das wird durch zwei Ausgaben auf
den Port CLKPR bewirkt.
Dann wird die Timerlänge auf 147
gesetzt (Schreiben in Compare-A-
Port OCR0A). Der Timer setzt sich
im CTC-Mode dann automatisch auf
Null zurück und beginnt neu.
Durch Schreiben von 74 in den
Compare-B-Port und durch das
Kontrollwort in TCCR0A wird
erreicht, dass bei halbem Timerwert
der Ausgangspin OC0B seine
Polarität wechselt (Toggle).
In Kontrollwort TCCR0B wird der
Vorteiler des Zählers auf 1024
eingestellt, der Zähler zählt jetzt
aufwärts.
Nach Setzen des SLEEP ENABLE
Bits wird der Prozessor mit dem
Befehl SLEEP schlafen gelegt, er
wacht nicht wieder auf.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 06: NF-


Erzeugung
Dasselbe Prinzip, aber anderes Timing: der
Prozessortakt wird bei den voreingestellten
1,2 MHz belassen, statt der LED wird ein
Piezo- oder 32-Ohm-Lautsprecher
angeschlossen.
Die Timer-Werte werden so eingestellt, dass
der Ausgang OC0B (PB1 an Pin 6) mit einer
Frequenz von 1000 Hz seine Polarität
wechselt (Vorteiler = 8, CTC bei 75, 1,2MHz /
8 / 75 = 2kHz, Polaritätswechsel am Ausgang
bei Zählerstand 38, zwei Durchläufe ergeben
eine volle NF-Schwingung, 2000 Hz / 2 = 1000
Hz).
Auch in diesem Beispiel wird die CPU
schlafen gelegt und nicht wieder aufgeweckt.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 07: Unterbrechung/Interrupt


• In diesem Beispiel wird demonstriert, wie ein Pegelwechsel an einem Eingangspin
dazu verwendet werden kann, die schlafende CPU aufzuwecken und eine Aktion
auszuführen (hier: Ein- bzw. Ausschalten einer LED).
• Der Eingangspin wird dazu mit einem internen Pull-Up-Widerstand auf +5V gezogen.
Das entsprechende Portbit wird maskiert, so dass nur Pegelwechsel an diesem Pin
Interrupts auslösen können.
• Wenn die Taste den Pin auf 0V zieht, wird ein Interrupt ausgelöst. Wird die Taste
wieder losgelassen, löst der Pegelwechsel erneut einen Interrupt aus.
• Bei einem Interrupt legt die CPU die aktuelle Adresse auf dem Stapel im SRAM ab,
verzweigt zu einer festen Adresse (Interrupt-Vektor) und bearbeitet die dortigen
Befehle. Bei der Rückkehr wird die auf dem Stapel abgelegte Adresse wieder geholt
und die Verarbeitung an der Adresse fortgesetzt, bei der die Unterbrechung auftrat.
• Jede Unterbrechungsmöglichkeit (beim ATtiny13 gibt es 10) hat ihren eigenen Platz
in der Vektortabelle, so dass sehr schnell auf ein Ereignis reagiert werden kann.
• Weitere Unterbrechungen werden so lange unterbunden, bis die Service-Routine
beendet ist. Danach kann dann die nächste Unterbrechung bearbeitet werden. Die
Bearbeitung mehrer gleichzeitiger Interrupts erfolgt nach einer Prioritätsreihenfolge:
je höher in der Tabelle de Vektor steht (niedrigere Adresse), desto vorrangiger.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 07: Schaltbild

Schalter an PB4 angeschlossen, LED an PB1 angeschlossen,


PB4 mit internem Pull-Up auf +5V PB1 auf Null: LED ist an
zieht Eingang auf Null Volt PB1 auf Eins: LED ist aus
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 07: Interrupt Vektoren


Register definieren: symbolische Namen
für bestimmte Register festlegen.

Die Interrupt-Vektor-Tabelle des ATtiny13:


Der Befehl an der Adresse 0000 wird beim
Start ausgeführt (Sprung zum Label main:).
Der Interrupt INT0 wird hier nicht benutzt,
an Adresse 0001 erfolgt ein einfacher
Rücksprung vom Interrupt (reti). Bei einem
Pegelwechsel an Pin 3 wird der PCINT0
Interrupt an Adresse 0002 angesprungen,
der nach Label intpcint: verzweigt. Alle
anderen Vektoren werden nicht benutzt.

Die Interupt-Service-Routine intpcint: stellt


als erstes fest, ob der Tasteneingang Null
der eins ist. Bei Null wird der rjmp nicht
ausgeführt.
Ist er Null, wird die LED angeschaltet und
die Routine beendet (reti).
Ist er Eins, wird die LED ausgeschaltet und
die Routine beendet (reti).
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 07: Anstoßen des Ganzen (Init)


Hauptprogramm, wird beim Reset
ausgeführt (Adresse 0000: Sprungbefehl
nach main:).
Der „Stapel“ im SRAM wird dazu benutzt,
um beim Interrupt die Rücksprungadresse
dort abzulegen und bei reti wieder dorthin
zu springen.
Der LED-Ausgang wird initiiert.
Der Tasten-Eingang wird definiert und der
Pull-Up-Widerstand eingeschaltet.
Die Maske in PCMSK wählt den Eingang
aus, bei dem Interrupt erfolgen soll (Bit 4).
Im Int-Maskenregister GIMSK wird der
PCINT0-Interrupt ermöglicht.
Im Statusregister der CPU wird das
Interrupt-Bit gesetzt, die CPU lässt Ints zu.
Das SLEEP ENABLE Bit wird gesetzt.
Die CPU wird mit SLEEP schlafen gelegt,
wacht beim Interrupt auf, führt ihn aus, und
wird anschließend wieder zu Bett gebracht.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 07: Testaufbau


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13

Eine Einführung in Aufbau, Funktionsweise,


Programmierung und Nutzen von Mikroprozessoren

Teil 8: gavrasmw und weitere Beispiele


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

gavrasmw – Leichter fensterln


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

gavrasmw - Setup
Einmal einstellen: wo ist das Assembler-Programm gavrasm, wo ist meine
Quellcode-Datei, welche Einstellungen beim Assemblieren
hätten‘s denn gern?
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

gavrasmw – Kleiner Editor auf Knopfdruck


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

gavrasmw macht eine Batch-Datei


Das mühsame Eintippen von Pfaden wird von gavrasmw erledigt und in einer
Batch-Datei abgelegt.

Zum Assemblieren einfach die Batch-Datei ausführen lassen oder den


Menuepunkt „Assemble“ drücken, schon geht gavrasm voll ab.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 08:
Taster macht Töne
• Morsetongenerator
• Kombiniert Beispiel 6 (NF-Erzeugung mit Timer)
und Beispiel 7 (Interrupt-gesteuerte
Tastenüberwachung) zu einem praktischen
Gerät
• Minimaler Stromverbrauch wegen CPU-
Schlafmodus und Timer-Automatik
• Minimale Außenbeschaltung (keine
Kondensatoren, ein Widerstand)
• Genauso groß wie ein 555, aber viel flexibler
(beliebige NF-Frequenz ohne
Hardwareänderung und alleine durch
Programmieren einstellbar)
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 08:
Taster macht Töne II
• Ändern der NF-Frequenz durch Ändern
einer Zahl im Quellcode
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 09: Tonhöhen-Einstellung


• In diesem Beispiel wird die Tonhöhe der NF-Frequenz mit einem
Potentiometer eingestellt.
• Die Poti-Stellung wird mit einem AD-Wandler von Analog (0..5 Volt) in eine
digitale Zahl verwandelt (0..1023) und stellt die Timer-Auflösung durch
Teilen durch vier auf Werte zwischen 0 und 255 ein.
• Der AD-Wandler wird einmalig gestartet, nach Ende der Umwandlung
unterbricht der AD-Wandler die CPU, schreibt das Ergebnis in ein Register
und startet sich automatisch wieder selbst.
• Die angeschlossene Taste unterbricht beim Schließen und Öffnen die CPU,
schreibt den aktuellen Tonhöhenwert in den Timer und startet (Taster
geschlossen) oder stoppt (Taster offen) die Ausgabe der NF über den
Ausgangs-Pin.
• Die CPU wird schlafen gelegt und nur durch die beiden Interrupts
aufgeweckt. Der Interrupt wird in der Interrupt-Service-Routine bearbeitet,
anschließend wird die CPU wieder schlafen gelegt.
• Beide Interrupts sind voneinander völlig entkoppelt und können zu
beliebigen Zeiten auftreten, ohne sich gegenseitig zu stören.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 09: Hardware


Der Kondensator am
Poti (10 nF) dient zum
Abblocken von
Wechselspannungs-
und HF-Einstreu-
ungen. ADC-Wandler
sind da sehr
empfindlich.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 09:
Quellcode
Im Schaltbild ist das Poti an Pin2 (ADC-
Kanal 3) angeschlossen.

In den Registern rTonA und rTonB legt


der AD-Wandler sein Ergebnis ab.

Die Tastatur löst wieder den PCINT0


Interrupt aus.

Der Interrupt-Vektor „ADC conversion


complete“ wird angesteuert, wenn der
ADC mit einer Wandlung fertig ist.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 09: Quellcode II


Der Tasten-Interrupt stellt
fest, ob die Taste gedrückt
ist.
Die Tonhöhe aus dem
Register in den Timer
übernehmen.
Bei gedrückter Taste NF an
OC0A und OC0B
einschalten.
Bei losgelassener Taste NF
ausschalten.
Der ADC-Interrupt liest das
Umwandlungsergebnis.
Teilt den Wert durch vier
und schreibt den Wert für
CompA in rTonA.
Teilt diesen Wert durch 2
und schreibt ihn in rTonB.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 09: Quellcode III


Der Rest des Quellcodes ist ähnlich wie bei anderen Beispielen (Stapel einrichten,
Einstellen und starten des Timers, Interrupts ermöglichen, Schlafmodus einstellen
Schlaf-Loop.
Nur der Start des AD-Wandlers zu Beginn im Hauptprogramm ist neu. Zuerst wird der
Eingangstreiber von PB3 abgeschaltet, beim Betrieb als AD-Kanal wird der nicht
gebraucht (Strom und Noise ein sparen).
Dann wird die Referenzspannung (Betriebsspannung) und der zu messende Kanal
ADC3 ausgewählt.
Im Kontrollport ADCSRB wird als Triggerquelle der Freilauf gewählt.
Im Kontrollport ADCSRA wird der ADC gestartet, die Triggerung eingeschaltet, der
Interrupt ermöglicht und der Teiler für die Wandlung aus 128 eingestellt (langsam).
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 10: Morsebake


• In dieser Anwendung wird von einem ATtiny13
auf Knopfdruck ein voreingestellter Morsetext
ausgegeben.
• Text, Gebegeschwindigkeit und Tonhöhe werden
vor dem Programmieren im Quelltext eingestellt.
• Die Tastenüberwachung und die NF-Ausgabe
erfolgt rein Timer- und Interrupt-gesteuert.
• Bei der Timer-Ausgabe von Tönen (NF an) und
Pausen (NF aus) wird die Anzahl der Timer-
Durchläufe gezählt (Anzahl der NF-Halbwellen).
Dadurch wird die Dauer des Tons bzw. der Pause
überwacht und nach Ablauf des Zählers die
nächstfolgende Aktion eingeleitet.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 10: Einstellung der Parameter

Schaltung: Die LED diesmal an


PB2, der Lautsprecher an PB1 und
die Taste wieder an PB4.
Die Gebegeschwindigkeit und die
Tonhöhe werden als Konstanten
vorgegeben.
Daraus abgeleitete Konstanten
errechnet, die bei der
Ablaufsteuerung eingesetzt werden.
Die sich ergebenden Werte werden
überprüft (Überläufe, Unterläufe),
damit beim Assemblieren schon
erkannt wird, ob etwas aus dem
Ruder läuft.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 10: Auszug


Morsetabelle
Die Morsetabelle ist im
Programmspeicher in Binärform
abgelegt. Hier die ASCII-Zeichen von 30
bis 4F hex.
Jedes Morsezeichen benötigt zwei
Byte: im ersten ist die Abfolge von
kurzen und langen Tönen kodiert, (bei
einer „0“: 0b11111000 = 5 mal lang), im
zweiten die Anzahl kurzer und langer
Töne zusammen (bei einer „0“: 5).
Verkehrszeichen sind auf ASCII-
Zeichen gelegt, für die es kein Morse-
Äquivalent gibt (z.B. Verkehrsanfang ist
ASCII-Zeichen <).
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Beispiel 10: Textablage


Der auszugebende Text ist auch im Programmspeicher abgelegt. Er wird aus
dem Programmspeicher ab dem Label MorseText: ausgelesen, in
Morsezeichen übersetzt und ausgegeben. Wenn das Zeichen 0 erreicht wird,
ist der Text zu Ende (Null-terminierter String) und die Ausgabe wird beendet.

Aufnahme abspielen: hier klicken =>


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Programmierung von ATMEL AVR


Mikroprozessoren am Beispiel des
ATtiny13
Eine Einführung in Aufbau, Funktionsweise,
Programmierung und Nutzen von Mikroprozessoren

Teil 8: Ein Sinusgenerator mit AVR-Timer


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Sinus mit Timer und RC-Filter


Aufgabe: Einen Sinus erzeugen, hier: 1750 Hz
Einfache Lösung: Timer mit CTC, toggeln des OCR0A- oder OR0B-Ausgangs und
RC-Filter zum Sieben der Oberwellen nachschalten
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Nachteile des Verfahrens


• Schaltfrequenz des Ausgangs =
2 * Ausgangsfrequenz
• Erste Oberwelle des Rechteck-Signals =
3 * Grundwelle
• Schlechte Dämpfung von RC-Filtern bei
3 * Grundfrequenz
• Für ausreichende Dämpfung ist größeres RC-Glied
notwendig
• Dadurch schon hohe Dämpfung bei der Nutzfrequenz
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Besser: Sinusgenerator mit PWM


• Prinzip der Pulsweitenmodulation:
Die Zeitdauer im High-Zustand und die Zeitdauer im
Low-Zustand bei einem Rechteckgenerator sind
variabel.
Sind beide gleich, ergibt sich am Ausgang im Mittel
die halbe Betriebsspannung.

_____ _____ _____ __


_| |_____| |_____| |_____|
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Prinzip der Pulsweitenmodulation


• Ist der High-Zustand kürzer als der Low-Zustand,
ergibt sich eine niedrigere mittlere Spannung:
_ _ _ _
_| |________| |________| |_________| |_
• Ist der High-Zustand länger als der Low-Zustand,
ergibt sich eine höhere mittlere Spannung:
________ ________ _________ ___
_| |_| |_| |_|
• Mit Pulsweitenmodulation lassen sich analoge
Spannungen zwischen Null und Betriebsspannung
erzeugen.
• Die Auflösungsgenauigkeit der „Analogspannung“
ist nur von der Schrittzahl abhängig.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Timer als PWM-Generator


• Die Anzahl Schritte der PWM ergibt sich aus dem Takt-
generator (hier: 9,6MHz), der gewünschten Auflösung
(hier: 32) und der gewünschten Frequenz (hier: 1750).
n = 9.600.000 / 32 / 1750 = 171,43
• Anzahl Schritte der PWM wird mit dem CTC-Wert fest-
gelegt (CTC = Clear Timer on Compare). Hier erfolgt das
bei 171. Dieser Wert kommt nach Compare Match A.
• Die PWM-Werte müssen zwischen 0 und 171 variieren.
Diese Werte kommen nach Compare Match B.
• Compare Match A setzt den Zähler auf Null und den
Ausgang auf High. Bei Erreichen von Compare Match B
wird der Ausgang Low. Je größer Compare Match B,
desto höher die Spannung.
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

PWM-Werte für einen Sinus


Sinus-PWM mit Schrittweite 171

180

160

140

120

100
Schritte

80

60

40

20

0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Auflösung = 32
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Auslegung des RC-Filters mit SinePwm


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Graphische Ausgabe von SinePwm


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Zu großes RC
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Zu kleines RC
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Emitterfolger als Treiber


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Die Schaltung
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Die Software
Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Das Ergebnis – PWM-Ausgangssignal


Programmierung von ATMEL AVR Mikroprozessoren am Beispiel des ATtiny13, http://www.avr-asm-tutorial.net

Das Ergebnis – Analog-Ausgangssignal

Oben:
Erstes RC-
Glied

Zweistrahl-
oszillo-
gramm

Unten:
Emitterfolger-
Ausgang
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp01_loop.asm

; **************************************************************
; * Das langweiligste Programm der Welt: der unendliche Loop *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.NOLIST
.INCLUDE "tn13def.inc"
.LIST
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |
; |PB4 PB1|
; 4| |
; O----|Gnd PB0|
; |__________|
;
;
loop:
rjmp loop
;
; End of source code

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp01_loop.asm1/20/2009 7:48:15 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp02_led.asm

; ********************************************************
; * Das zweitlangweiligste Programm der Welt: LED an! *
; * (C)2005 by info@avr-asm-tutorial.net *
; ********************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
;
sbi DDRB,1 ; Bit 1 Port B ist Ausgang
cbi PORTB,1 ; Ausgang auf logisch 0
loop:
rjmp loop
;
; End of source code

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp02_led.asm1/20/2009 7:48:16 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp03_blink.asm

; **********************************************************
; * Mehr Action: LED-Blinker *
; * (C)2005 by info@avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
sbi DDRB,1 ; PB1 ist Ausgang
loop:
cbi PORTB,1 ; Ausgang auf Null
sbi PORTB,1 ; Ausgang auf Eins
rjmp loop ; und von vorne
;
; End of source code

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp03_blink.asm1/20/2009 7:48:17 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam.asm

; **********************************************************
; * Mehr Action: LED-Blinker mit Verzoegerung *
; * (C)2005 by info@avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "tn12def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Benutzte Register
;
; ZH:ZL (R31:R30) ist Zaehlregister fuer Verzoegerung
;
; Programm
;
sbi DDRB,0 ; PB1 ist Ausgang
loop:
sbi PORTB,0 ; Ausgang auf Eins (LED ist aus)
loop1:
sbiw ZL,1 ; Ziehe von ZH:ZL eine 1 ab
brne loop1 ; wenn noch nicht Null, wiederhole
cbi PORTB,0 ; Ausgang auf Null (LED ist an)
loop2:
sbiw ZL,1 ; Ziehe von ZH:ZL eine 1 ab
brne loop2 ; wenn noch nicht Null, wiederhole
rjmp loop ; und das Ganze von vorne
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam.asm1/20/2009 7:48:18 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam_takte.asm

; **********************************************************
; * Mehr Action: LED-Blinker mit Verzoegerung *
; * (C)2005 by info@avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Benutzte Register
;
; ZH:ZL (R31:R30) ist Zaehlregister fuer Verzoegerung
;
; Programm
;
sbi DDRB,1 ; PB1 ist Ausgang
loop:
sbi PORTB,1 ; 1 Takt, Ausgang auf Eins (LED ist aus)
;
; Verzoegerungsschleife Eins
; Registerpaar Z = ZH:ZL wird von Null rueckwaerts auf Null gezaehlt
;
loop1:
sbiw ZL,1 ; 2 Takte, Ziehe von ZH:ZL eine 1 ab
brne loop1 ; 2 Takte bei Sprung, 1 Takt bei Nicht-Sprung
;
; 65.535 mal zwei+zwei Takte plus 1 mal zwei+ein Takt =
; 262.143 Takte
;
cbi PORTB,1 ; 1 Takt, Ausgang auf Null (LED ist an)
;
; Noch mal 262.143 Takte Verzoegerung
;
loop2:
sbiw ZL,1 ; Ziehe von ZH:ZL eine 1 ab
brne loop2 ; wenn noch nicht Null, wiederhole
;
; Ende Verzoegerungsschleife
;
rjmp loop ; 2 Takte, und das Ganze von vorne
;
; Zeitbilanz:
; Ausgang 1 setzen: 1 Takt
; Verzoegerungsschleife 1: 262.143 Takte
; Ausgang 0 setzen: 1 Takt
; Verzoegerungsschleife 2: 262.143 Takte
; Ruecksprung an Anfang: 2 Takte
; --------------------------------------
; Summe 524.290 Takte
;
;
; Interner Taktgenerator ATtiny13 = 1.200.000 Takte pro Sekunde
;
; Blinkfrequenz: = 1.200.000 / 524.290 = 2,2888 Hz
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam_takte.asm1/20/2009 7:48:20 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam_tn12.asm

; **********************************************************
; * Mehr Action: LED-Blinker mit Verzoegerung *
; * Original fuer ATtiny13, fuer ATtiny12 umgeschrieben *
; * (C)2005 by info@avr-asm-tutorial.net *
; **********************************************************
;
.INCLUDE "tn12def.inc"
;
;
; Anmerkung zur Umstellung des Programms von ATtiny13 auf ATtiny12:
;
; Der ATtiny12 beherrscht die Wort-Instruktionen adiw und sbiw nicht.
; Sie muessen daher ersetzt werden durch entsprechende Byte-Operationen.
; gavrasm hat hier einen Bug und erkennt die ungueltige Operation nicht!
;
; Der Chip mit der Nummer 2 ist fertig mit diesem Programm gebrannt.
;
; Schaltbild:
; ATMEL ATtiny12
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Benutzte Register
;
; ZH:ZL (R31:R30) ist Zaehlregister fuer Verzoegerung
;
; Konstanten
;
.EQU bBlink = 1 ; blinkendes Portbit
;
; Programm
;
sbi DDRB,bBlink ; PB1 ist Ausgang
loop:
sbi PORTB,bBlink ; Ausgang auf Eins (LED ist aus)
loop1:
subi ZL,1 ; Ziehe von ZL eine 1 ab
breq loop1a ; Null geworden, teste auf MSB=Null
brcc loop1 ; kein Carry, weiter Loop1 bis Null
dec ZH ; MSB eins abziehen
rjmp loop1 ; weiter mit loop1 bis Null
loop1a:
tst ZH ; teste MSB auf Null
brne loop1 ; noch nicht Null, weiter mit loop1 bis Null
cbi PORTB,bBlink ; Ausgang auf Null (LED ist an)
loop2:
subi ZL,1 ; Ziehe von ZL eine 1 ab
breq loop2a ; Null, pruefe MSB auf Null
brcc loop2 ; kein Carry, weiter loop2 bis Null
dec ZH ; MBN eins abziehen
rjmp loop2 ; weiter mit loop2 bis Null
loop2a:
tst ZH ; teste MSB auf Null
brne loop2 ; noch nicht Null, weiter mit loop2 bis Null
rjmp loop ; und das Ganze von vorne
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp04_blink_langsam_tn12.asm1/20/2009 7:48:21 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp05_blink_Timer.asm

; **************************************************************
; * Der Timer blinkt alleine *
; * (C)2005 by avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
; Programmbeginn
;
; Internen Prozessortakt durch 32 teilen
; Takt = 9,6 MHz / 32 = 300 kHz
;
ldi rmp,0b10000000 ; Vorteiler-Bit auf Eins setzen
out CLKPR,rmp
ldi rmp,0b00000101 ; Prozessorvorteiler auf 32 setzen
out CLKPR,rmp
;
; PB1=OC0B als Ausgang setzen
;
sbi DDRB,1
;
; 8-Bit-Timer mit 300 kHz Prozessortakt mit Vorteiler durch 1024
; 300 kHz / 1024 = 293 Hz, / 147 = 2 Hz, /2 = 1 Hz
;
ldi rmp,147 ; Setze Compare A auf 147 (Ende Zaehler)
out OCR0A,rmp
ldi rmp,74 ; Setze Compare B auf halben Timer-Wert
out OCR0B,rmp
ldi rmp,0b00010010 ; CTC, toggle Ausgang B bei Compare Match
out TCCR0A,rmp
ldi rmp,0b00000101 ; Vorteiler durch 1024, Timer starten
out TCCR0B,rmp
ldi rmp,0b00100000 ; SLEEP Modus ermoeglichen
out MCUCR,rmp
sleep ; Prozessor schlafen legen
; Unsinn
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp05_blink_Timer.asm1/20/2009 7:48:23 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp05_blink_Timer_kurz.asm

; **************************************************************
; * Der Timer blinkt alleine *
; * (C)2005 by avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; | |6 ___
; |PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
; Programmbeginn
;
; Internen Prozessortakt durch 32 teilen
; Takt = 9,6 MHz / 32 = 300 kHz
;
ldi rmp,0b10000000 ; Vorteiler-Bit auf Eins setzen
out CLKPR,rmp
ldi rmp,0b00000101 ; Prozessorvorteiler auf 32 setzen
out CLKPR,rmp
;
; PB1=OC0B als Ausgang setzen
;
sbi DDRB,1
;
; 8-Bit-Timer mit 300 kHz Prozessortakt mit Vorteiler durch 1024
; 300 kHz / 1024 = 293 Hz, / 147 = 2 Hz, /2 = 1 Hz
;
ldi rmp,147 ; Setze Compare A auf 147 (Ende Zaehler)
out OCR0A,rmp
ldi rmp,74 ; Setze Compare B auf halben Timer-Wert
out OCR0B,rmp
ldi rmp,0b00010010 ; CTC, toggle Ausgang B bei Compare Match
out TCCR0A,rmp
ldi rmp,0b00000101 ; Vorteiler durch 1024, Timer starten
out TCCR0B,rmp
ldi rmp,0b00100000 ; SLEEP Modus ermoeglichen
out MCUCR,rmp
sleep ; Prozessor schlafen legen
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp05_blink_Timer_kurz.asm1/20/2009 7:48:24 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp06_lsp.asm

; **************************************************************
; * Ein Lautprecher macht Toene *
; * (C)2005 by avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2| ___
; | |6 \_/
; |PB4 PB1|--|_|--O + 5 Volt
; 4| | LSP
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
; Programmbeginn
;
;
; PB1=OC0B als Ausgang setzen
;
sbi DDRB,1
sbi DDRB,0
;
; 8-Bit-Timer mit 1,2 MHz Prozessortakt mit Vorteiler durch 8
; 1,2 MHz / 8 = 150 kHz, / 75 = 2000 Hz, /2 = 1000 Hz
;
ldi rmp,75 ; Setze Compare A auf 147 (Ende Zaehler)
out OCR0A,rmp
ldi rmp,38 ; Setze Compare B auf halben Timer-Wert
out OCR0B,rmp
ldi rmp,0b00010010 ; CTC, toggle Ausgang B bei Compare Match
out TCCR0A,rmp
ldi rmp,0b00000010 ; Vorteiler durch 8, Timer starten
out TCCR0B,rmp
ldi rmp,0b00100000 ; SLEEP Modus ermoeglichen
out MCUCR,rmp
sleep ; Prozessor schlafen legen
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp06_lsp.asm1/20/2009 7:48:26 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp07_keyint.asm

; *********************************************************
; * Angeschlossener Taster unterbricht und steuert LED an *
; * (C)2005 by info@avr-asm-tutorial.net *
; *********************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2|
; / 3| |6 ___
; 0 Volt O--O O--|PB4 PB1|--|___|--|<|--O + 5 Volt
; 4| | 330 LED
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose register
.DEF rimp = R17 ; Interrupt multipurpose register
;
; Constants
;
;
; Reset- und Interrupt-Vektoren
;
.CSEG ; Assembliere in den Programm-Flash-Speicher
.ORG $0000 ; beginne mit Adresse 0
;
; Sprungvektoren fuer Reset und Interrupts
;
rjmp main ; Reset vector
reti ; Int0 interrupt vector
rjmp intpcint ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
reti ; ADC conversion complete vector
;
; PCINT0 Service Routine
; wird jedes Mal ausgefuehrt, wenn sich der Pegel am
; Pin 3 (=PB4) aendert
;
intpcint:
sbic PINB,4 ; Ueberspringe Befehl wenn PB4 Null
rjmp intpcint1 ; springe weil PB4 = Eins
cbi PORTB,1 ; schalte LED an
reti ; Kehre vom Interrupt zurueck
intpcint1:
sbi PORTB,1 ; schalte LED aus
reti ; Kehre vom Interrupt zurueck
;
; Main program start
;
main:
;
; Stapelzeiger setzen fuer Rueckkehr-Adressen vom Interrupt
;
ldi rmp,LOW(RAMEND) ; Stapelzeiger auf Ende SRAM
out SPL,rmp
;
; Angeschlossene Hardware initiieren
;
sbi DDRB,1 ; LED-Ausgang als Ausgang definieren
sbi PORTB,1 ; LED ausschalten
cbi DDRB,4 ; Taster-Eingang als Eingang definieren
sbi PORTB,4 ; Internen Pull-Up-Widerstand einschalten
;
; Pin-Change-Interrupt fuer Taste aktivieren
;
ldi rmp,0b00010000 ; Maskieren der aktiven Eingaenge
out PCMSK,rmp
ldi rmp,0b00100000 ; PCINT0-Interrupts ermoeglichen
out GIMSK,rmp
;
; Interrupts generell einschalten
;
sei ; Setze Interrupt Flagge
;
; Schlafmodus der CPU einstellen
;
ldi rmp,0b00100000 ; Schlafen ermoeglichen, Modus Idle
out MCUCR,rmp
;
; Loop mit Interrupt
;
loop:
sleep ; Prozessor schlafen legen
nop ; Tue nichts nach dem Aufwachen
rjmp loop ; Prozessor wieder schlafen legen
;
; Ende Quellcode
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp07_keyint.asm1/20/2009 7:48:27 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp08_morsekey.asm

; ************************************************
; * Angeschlossener Taster macht Toene *
; * (C)2005 by info@avr-asm-tutorial.net *
; ************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; |PB3 PB2| ___
; / 3| |6 \_/
; 0 Volt O--O O--|PB4 PB1|---|_|--O + 5 Volt
; 4| | LSP
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register Definitionen
;
.DEF rmp = R16 ; Multipurpose register
.DEF rimp = R17 ; Interrupt multipurpose register
;
; Constants
;
;
; Reset- und Interrupt Vektoren
;
.CSEG ; Assembliere in den Programm-Flash-Speicher
.ORG $0000 ; beginne mit Adresse 0
;
; Sprungvektoren fuer Reset und Interrupts
;
rjmp main ; Reset vector
reti ; Int0 interrupt vector
rjmp intpcint ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
reti ; ADC conversion complete vector
;
; PCINT0 Service Routine
; wird jedes Mal ausgefuehrt, wenn sich der Pegel am
; Pin 3 (=PB4) aendert
;
intpcint:
sbic PINB,4 ; Ueberspringe 1 Befehl wenn PB4 Null
rjmp intpcint1 ; springe weil PB4 = Eins
ldi rmp,0b00010010 ; CTC, Ausgang B bei Cmp Match auf Toggle
out TCCR0A,rmp
reti ; Kehre vom Interrupt zurueck
intpcint1:
ldi rmp,0b00110010 ; CTC, Ausgang B bei Cmp Match auf 1
out TCCR0A,rmp
reti ; Kehre vom Interrupt zurueck
;
; Main program start
;
main:
;
; Stapelzeiger setzen fuer Rueckkehr-Adressen vom Interrupt
;
ldi rmp,LOW(RAMEND) ; Stapelzeiger auf Ende SRAM
out SPL,rmp
;
; Angeschlossene Hardware initiieren
;
sbi DDRB,1 ; Lautsprecher-Ausgang als Ausgang definieren
cbi DDRB,4 ; Taster-Eingang als Eingang definieren
sbi PORTB,4 ; Internen Pull-Up-Widerstand einschalten
;
; Tonerzeugung mit Timer TC0
; 8-Bit-Timer mit 1,2 MHz Prozessortakt mit Vorteiler durch 8
; 1,2 MHz / 8 = 150 kHz, / 75 = 2000 Hz, /2 = 1000 Hz
;
ldi rmp,55 ; Setze Compare A auf 147 (Ende Zaehler)
out OCR0A,rmp
ldi rmp,38 ; Setze Compare B auf halben Timer-Wert
out OCR0B,rmp
ldi rmp,0b11110010 ; CTC, Ausg. A + B bei Cmp Match auf 1
out TCCR0A,rmp
ldi rmp,0b00000010 ; Vorteiler durch 1024, Timer starten
out TCCR0B,rmp
;
; Pin-Change-Interrupt fuer Taste aktivieren
;
ldi rmp,0b00010000 ; Maskieren der aktiven Eingaenge
out PCMSK,rmp
ldi rmp,0b00100000 ; PCINT0-Interrupts ermoeglichen
out GIMSK,rmp
;
; Interrupts generell einschalten
;
sei ; Setze Interrupt Flagge
;
; Schlafmodus der CPU einstellen
;
ldi rmp,0b00100000 ; Schlafen ermoeglichen, Modus Idle
out MCUCR,rmp
;
; Loop mit Interrupt
;
loop:
sleep ; Prozessor schlafen legen
nop ; Tue nichts nach dem Aufwachen
rjmp loop ; Prozessor wieder schlafen legen
;
; Ende Quellcode
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp08_morsekey.asm1/20/2009 7:48:28 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp09_adcmorsekey.asm

; *********************************************************
; * Angeschlossener Taster macht Toene, Tonhoehe mit Poti *
; * (C)2005 by info@avr-asm-tutorial.net *
; *********************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | |
; +0..5 Volt O-------|ADC3 PB2| ___
; / 3| |6 \_/
; 0 Volt O--O O--|PB4 PB1|---|_|--O + 5 Volt
; 4| | LSP
; 0 Volt O----|Gnd PB0|
; |__________|
;
; Register Definitionen
;
.DEF rTonA = R14 ; Tonhoehe = TC0 Compare Match A
.DEF rTonB = R15 ; halbe Tonhoehe = TC0 Compare Match B
.DEF rmp = R16 ; Multipurpose register
.DEF rimp = R17 ; Interrupt multipurpose register
;
; Reset- und Interrupt Vektoren
;
.CSEG ; Assembliere in den Programm-Flash-Speicher
.ORG $0000 ; beginne mit Adresse 0
;
; Sprungvektoren fuer Reset und Interrupts
;
rjmp main ; Reset vector
reti ; Int0 interrupt vector
rjmp intpcint ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
rjmp intadc ; ADC conversion complete vector
;
; PCINT0 Service Routine
; wird jedes Mal ausgefuehrt, wenn sich der Pegel am
; Pin 3 (=PB4) aendert
;
intpcint:
sbic PINB,4 ; Ueberspringe Befehl wenn PB4=Null
rjmp intpcint1 ; springe weil PB4 = Eins
out OCR0A,rTonA ; Tonhoehe einstellen
out OCR0B,rTonB
ldi rimp,0b01010010 ; CTC, Ausg. A und B bei
out TCCR0A,rimp ; compare match auf toggle (NF an)
ldi rimp,0b00000010 ; Vorteiler 1024, Timer start
out TCCR0B,rimp
reti ; Kehre vom Interrupt zurueck
intpcint1:
ldi rimp,0b11110010 ; CTC, Ausgaenge A und B bei
out TCCR0A,rmp ; Compare Match auf 1 stellen (NF aus)
reti ; Kehre vom Interrupt zurueck
;
; AD-Wandler hat einen Wert gewandelt, abholen und speichern
;
intadc:
in rTonA,ADCL ; Lese ADC-Wert, niedriges Byte
in rTonB,ADCH ; Lese ADC-Wert, hohes Byte
lsr rTonB ; durch 2 teilen
ror rTonA
lsr rTonB ; durch 4 teilen
ror rTonA
mov rTonB,rTonA ; Ergebnis kopieren
lsr rTonB ; durch zwei teilen
reti ; fertig und zureck
;
; Main program start
;
main:
;
; Stapelzeiger setzen fuer Rueckkehr-Adressen vom Interrupt
;
ldi rmp,LOW(RAMEND) ; Stapelzeiger auf Ende SRAM
out SPL,rmp
;
; Angeschlossene Hardware initiieren
;
sbi DDRB,1 ; Lautsprecher-Pin als Ausgang definieren
cbi DDRB,4 ; Taster-Eingang als Eingang definieren
sbi PORTB,4 ; Internen Pull-Up-Widerstand einschalten
;
; AD-Wandler starten
;
ldi rmp,0b00001000 ; PB3 Treiber aus, spart Strom
out DIDR0,rmp
ldi rmp,0b00000011 ; Referenzspannung UB, ADC3 waehlen
out ADMUX,rmp
ldi rmp,0b00000000 ; Freilauf waehlen (startet selbst)
out ADCSRB,rmp
ldi rmp,0b11101111 ; ADC starten, Autostart,
out ADCSRA,rmp ; Int Enable, Teiler auf 128
;
; Tonerzeugung mit Timer TC0
; 8-Bit-Timer mit 1,2 MHz Prozessortakt mit Vorteiler durch 8
; 1,2 MHz / 8 = 150 kHz, / 75 = 2000 Hz, /2 = 1000 Hz
; Start erfolgt erst bei PCINT-Interrupt
;
ldi rmp,75 ; Setze Compare A auf 147 (Ende Zaehler)
mov rTonA,rmp ; speichere in Register
ldi rmp,38 ; Setze Compare B auf halben Timer-Wert
mov rTonB,rmp ; speichere in Register
;
; Pin-Change-Interrupt fuer Taste aktivieren
;
ldi rmp,0b00010000 ; Maskieren der aktiven Eingaenge
out PCMSK,rmp
ldi rmp,0b00100000 ; PCINT0-Interrupts ermoeglichen
out GIMSK,rmp
;
; Interrupts generell einschalten
;
sei ; Setze Interrupt Flagge
;
; Schlafmodus der CPU einstellen
;
ldi rmp,0b00100000 ; Schlafmodus auf Idle
out MCUCR,rmp
;
; Loop mit Interrupt
;
loop:
sleep ; Prozessor schlafen legen
nop ; Tue nichts nach dem Aufwachen
rjmp loop ; Prozessor wieder schlafen legen
;
; Ende Quellcode
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp09_adcmorsekey.asm1/20/2009 7:48:30 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp10_morsebake.asm

; **************************************************************
; * Angeschlossener Taster startet Morseausgabe eines Texts *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "tn13def.inc"
;
; Schaltbild:
; ATMEL ATtiny13
; ___ ____
; ___ 1/ |_| |8
;+5 Volt O--|___|----|Res Vcc|----O + 5 Volt
; | | ___
; |PB3 PB2|--|___|--|<|--O + 5 Volt
; / 3| |6 _ LED
; 0 Volt O--O O--|PB4 PB1|---|_|--O + 5 Volt
; 4| | /\
; 0 Volt O----|Gnd PB0| ---
; |__________| LSP
;
; Waehlbare Konstanten
;
.EQU cSpeed = 90 ; Gebegeschwindigkeit in bpm, 5..500 bpm
.EQU cTone = 1000 ; Tonhoehe in Hz, 300..8000 Hz
;
; Festgelegte Konstanten
;
.EQU fClock = 1200000
.EQU cTc0Div = 8
;
; Berechnete Konstanten
;
.EQU cTc0CmpA = fClock/cTc0Div/cTone/2
.EQU cTc0CmpB = cTc0CmpA/2
.EQU cTc0N = cTone*16/cSpeed
.EQU cTc0N2 = 2*cTc0N ; zweifach lange Zeit
.EQU cTc0N3 = 3*cTc0N ; dreifach lange Zeit
;
; Ueberpruefen der eingestellten Werte
;
.IF cTc0CmpA > 255
.ERROR "Ton zu niedrig!"
.ENDIF
.IF cTc0CmpA < 8
.ERROR "Ton zu hoch!"
.ENDIF
.IF cTc0N3 > 65535
.ERROR "Frequenz zu niedrig!"
.ENDIF
.IF cTc0N < 8
.ERROR "Frequenz zu hoch!"
.ENDIF
;
; Register Definitionen
;
.DEF rSreg = R15 ; Sicherungsregister fuer SREG in Ints
.DEF rmp = R16 ; Multipurpose register
.DEF rimp = R17 ; Interrupt multipurpose register
.DEF rFlg = R18 ; Flaggen
.EQU bAktiv = 0 ; Ausgabe ist aktiv
.EQU bPKurz = 1 ; Zeichenausgabe
.EQU bPLang = 2 ; Pause zwischen Zeichen
.DEF rSig = R19 ; Auszugebendes Morsezeichen
.DEF rLen = R20 ; Anzahl Kurz und Lang
; frei R21..R23
.DEF rCntL = R24 ; Zaehler fuer Anzahl Halbwellen NF, LSB
.DEF rCntH = R25 ; dto., MSB
;
; Reset- and interrupt vectors
;
.CSEG ; Assembliere in den Programm-Flash-Speicher
.ORG $0000 ; beginne mit Adresse 0
;
; Sprungvektoren fuer Reset und Interrupts
;
rjmp main ; Reset vector
reti ; Int0 interrupt vector
rjmp IntPcInt ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
rjmp IntTcCmpA ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
reti ; ADC conversion complete vector
;
; PCINT0 Service Routine
; wird jedes Mal ausgefuehrt, wenn der Pegel am
; Pin 3 (=PB4) wechselt (Taste wurde betaetigt)
;
IntPcInt:
in rSreg,SREG ; sichere Flags
sbic PINB,4 ; Ueberspringe naechsten Befehl wenn PB4 Null
rjmp IntPcInt1 ; springe weil PB4 = Eins
sbrc rFlg,bAktiv ; wenn schon aktiv: ignorieren
rjmp IntPcInt1 ; ist schon aktiv
ldi XH,HIGH(2*MorseText) ; Zeiger auf auszugebenden Text
ldi XL,LOW(2*MorseText)
ldi rCntH,0 ; Verzoegerung definieren
ldi rCntL,1
cbi PORTB,2 ; LED anschalten
sbr rFlg,(1<<bAktiv)|(1<<bPLang) ;
ldi rimp,cTc0CmpA ; Dauer Halbwelle in Compare A
out OCR0A,rimp
ldi rimp,cTc0CmpB ; Halbe Dauer Halbwelle in Compare B
out OCR0B,rimp
ldi rimp,0b00110010 ; CTC, Ausgang B bei Compare Match auf Stumm
out TCCR0A,rimp
ldi rimp,0b00000010 ; Timer prescaler auf 8
out TCCR0B,rimp
ldi rimp,0b00000100 ; OCIE0A Interrupt einschalten
out TIMSK0,rimp
IntPcInt1:
out SREG,rSreg ; stelle Flags wieder her
reti ; Kehre vom Interrupt zurueck
;
; Interrupt bei Timer-Ablauf
;
IntTcCmpA:
in rSreg,SREG ; Flags retten
sbiw rCntL,1 ; noch ein Durchlauf?
brne IntTcCmpARet
ldi rCntH,HIGH(cTc0N) ; Zaehler nachladen
ldi rCntL,LOW(cTc0N)
sbrs rFlg,bPKurz ; Kurzpausen-Bit gesetzt?
rjmp IntTcCmpANoKu ; Kurz-Bit nicht gesetzt
cbr rFlg,1<<bPKurz ; Kurz-Bit ruecksetzen
dec rLen ; Anzahl Kurz/Lang in Zeichen vermindern
brne IntTcCmpAStumm ; noch nicht Null, stumme Pause
sbr rFlg,1<<bPLang ;lange Pause zwischen Zeichen
ldi rCntH,HIGH(cTc0N2) ; Zaehler auf doppelte Dauer
ldi rCntL,LOW(cTc0N2)
IntTcCmpAStumm:
ldi rimp,0b00110010 ; Ausgang B bei Compare Match auf Stumm
out TCCR0A,rimp
rjmp IntTcCmpARet
IntTcCmpANoKu:
sbrs rFlg,bPLang ; Langpausen-Bit gesetzt?
rjmp IntTcCmpAAusgabe ; nei, weiter Zeichen ausgeben
cbr rFlg,1<<bPLang ; setze Langpausen-Bit zurueck
mov ZH,XH ; Z auf zu lesendes Zeichen setzen
mov ZL,XL
lpm ; Zeichen aus Flash in R0 einlesen
mov rimp,R0 ; Zeichen nach rimp kopieren
subi rimp,0x20 ; Ziehe Kontrollzeichen ab
brcs IntTcCmpAEnde ; Zeichen ist Kontrollzeichen, beende Ausgabe
adiw XL,1 ; X zeigt auf naechstes Zeichen
cpi rimp,$40 ; Kleinbuchstabe?
brcs IntTcCmpANoKlein
subi rimp,$20 ; Kleinbuchstabe in Grossbuchstabe
IntTcCmpANoKlein:
lsl rimp ; Tabellen-Offset mal zwei
ldi ZH,HIGH(2*MorseTabelle) ; Z zeigt auf Tabelle
ldi ZL,LOW(2*MorseTabelle)
add ZL,rimp ; Offset zum Tabellenanfang addieren
ldi rimp,0 ; Ueberlauf addieren
adc ZH,rimp
lpm ; Morsecode lesen
mov rSig,R0 ; in Signalspeicher kopieren
adiw ZL,1 ; zeige auf Zeichenlaenge
lpm ; Zeichenlaenge lesen
mov rLen,R0 ; in Zeichenlaengen-Speicher
sbrc rLen,7 ; Bit 7 signalisiert Leerzeichen
rjmp IntTcCmpALeer
IntTcCmpAAusgabe:
sbr rFlg,1<<bPKurz ; Kurzpausen-Bit setzen
lsl rSig ; naechstes Signal in Carry schieben
brcc IntTcCmpAPieps ; kurzes Signal
ldi rCntH,HIGH(cTc0N3) ; langes Signal
ldi rCntL,LOW(cTc0N3)
IntTcCmpAPieps:
ldi rmp,0b00010010 ; CTC, Ausgang B bei Compare Match auf Toggle
out TCCR0A,rmp
rjmp IntTcCmpARet
IntTcCmpALeer:
sbr rFlg,(1<<bPKurz)|(1<<bPLang) ; setze Kurz- und Langpausen-Bit
ldi rCntH,HIGH(cTc0N2) ; lange Pause
ldi rCntL,LOW(cTc0N2)
rjmp IntTcCmpAStumm
IntTcCmpAEnde:
sbi PORTB,2 ; LED ausschalten
ldi rimp,0b00000000
out TCCR0B,rimp ; Timer stoppen
out TIMSK0,rimp ; Timer-Interrupts abschalten
sbi PORTB,1 ; Ausgang auf ins schalten
cbr rFlg,1<<bAktiv ; Aktiv-Flag abschalten
IntTcCmpARet:
out SREG,rSreg ; Flag register wieder herstellen
reti
;
; Hauptprogramm nach dem Start
;
main:
;
; Stapelzeiger setzen fuer Rueckkehr-Adressen vom Interrupt
;
ldi rmp,LOW(RAMEND) ; Stapelzeiger auf Ende SRAM
out SPL,rmp
;
; Angeschlossene Hardware initiieren
;
sbi DDRB,1 ; Lautsprecher-Ausgang als Ausgang definieren
sbi PORTB,1 ; Lautsprecher-Ausgang auf Eins setzen
sbi DDRB,2 ; LED-Ausgang als Ausgang definieren
sbi PORTB,2 ; LED-Ausgang abschalten
cbi DDRB,4 ; Taster-Eingang als Eingang definieren
sbi PORTB,4 ; Internen Pull-Up-Widerstand einschalten
;
; Pin-Change-Interrupt fuer Taste aktivieren
;
ldi rmp,0b00010000 ; Maskieren der aktiven Eingaenge
out PCMSK,rmp
ldi rmp,0b00100000 ; PCINT0-Interrupts ermoeglichen
out GIMSK,rmp
;
; Interrupts generell einschalten
;
sei ; Setze Interrupt Flagge
;
; Schlafmodus der CPU einstellen
;
ldi rmp,0b00100000 ; Schlafen ermoeglichen, Modus Idle
out MCUCR,rmp
;
; Loop mit Interrupt
;
loop:
sleep ; Prozessor schlafen legen
nop ; Tue nichts nach dem Aufwachen

rjmp loop ; Prozessor wieder schlafen legen


;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (Ausgabe von links nach rechts, 0=Kurz, 1=Lang)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
Morsetabelle:
; Zeichen 20 .. 2F
.DB 0b00000000,0b10000000 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ~n
.DB 0b01101000,5 ; $ = á, °a
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0b10000000 ; & = nicht benutzt, leer
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0b10000000 ; * = nicht benutzt, leer
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
;
; Text fuer Morseausgabe
;
MorseText:
;.DB "<test test test>",0
; .DB "<HALLO! HIER IST EIN ATMEL TINY13 BEI DER ARBEIT!>",0,0
; .DB "paris paris paris paris paris paris paris paris paris paris ",0,0
.DB "<Die kalte Hand am Arsch des Sheriffs.>",0
;
; Ende Quellcode
;

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp10_morsebake.asm1/20/2009 7:48:32 PM
http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp11_1750_SinePwm.asm

; **************************************************************
; * Sinus-Generator mit einem AVR-Timer/Counter als Pulsweiten-*
; * Modulator, einem 3-fach-RC-Filter und einem Emitterfolger *
; * Geschrieben fuer einen ATtiny13 mit 9,6MHz internem Takt- *
; * oszillator, Ausgang ist OC0B (PB1, DIL-Pin 6), Version 1, *
; * Sinus eingestellt auf 1754,4 Hz, Aufloesung 32 Stufen, *
; * CTC=171, RC-Filter: R=2k2, C=2n2, Emitterfolger: Re=1k, *
; * BC183B, hFE=260 *
; * (C)2005 by http://www.avr-asm-tutorial.net * *
; **************************************************************
;
.NOLIST
.INCLUDE "tn13def.inc"
.LIST
;
; ***********************************************
; SCHALTBILD
; ***********************************************
;
; 10k ___________
; ___ 1/ |8
;+5V O-|___|-|RES VCC|--O+5V +5V
;T-Kurz __ 2| ATMEL |7 O
; |--O O--|PB3 PB2|--O PTT-Ausgang |C
;T-Lang __ 3| ATtiny13 |6 ___ ___ ___ B|/ BC
; |--O O--|PB4 PB1|--|___|-O-|___|-O-|___|-O--| 183B
; 4| PDIP |5 R | R | R | |\ E
; |--O--|GND PB0|-- --- --- --- O--O NF-
; |____________| C--- C--- C--- | aus
; | | | +-+
; --- --- --- | |Re
; +-+
; |
; ---
;
; ***********************************************
; EINSTELLUNGEN
; ***********************************************
;
; Anderbare Einstellungen, maximum = 37 Sekunden!
;
.EQU cKurz = 2 ; 2 Sekunden Dauer fuer kurzes Signal
.EQU cLang = 10 ; 10 Sekunden Dauer fuer langes Signal
.EQU bKurz = 3 ; Portbit fuer Taster kurze Signale
.EQU bLang = 4 ; Portbit fuer Taster lange Signale
.EQU bTx = 2 ; Portbit fuer PTT-Ausgang aktiv high
.EQU bPwm = 1 ; Portbit fuer PWM-Ausgang, nicht aenderbar
;
; ***********************************************
; REGISTER-DEFINITIONEN
; ***********************************************
;
; verwendet: R0 fuer Lesen aus Sinustabelle
; frei: R1..R14
.DEF rSreg = R15 ; Status retten bei Interrupts
.DEF rmp = R16 ; Multipurpose Register ausserhalb Int
.DEF rimp = R17 ; Multipurpose Register innerhalb Int
; frei: R18..R23
.DEF rDauerL = R24 ; Signaldauer-Zaehler, LSB
.DEF rDauerM = R25 ; dto., MSB
; frei: X, Y = R26..R29
; verwendet: Z = R31:R30 fuer Tabelle-Lesen
;
; ***********************************************
; KONSTANTEN
; ***********************************************
;
; Nicht veraenderbare Konstanten
;
.EQU cClock = 9600 ; Prozessortaktfrequenz in kHz
.EQU cCtc = 171 ; TC0-CTC
.EQU cKSin = cKurz * 1754 ; Anzahl Sinus bei kurzem Signal
.EQU cLSin = cLang * 1754 ; Anzahl Sinus bei langem Signal
.IF (cKSin>65536)||(cLSin>65536) ; Falsche Parameter
.ERROR "Zeit zu lang!"
.ENDIF
;
; Reset- and interrupt vectors
;
.CSEG
.ORG $0000
rjmp main ; Reset Vektor
reti ; INT0-Interrupt, nicht verwendet
rjmp PcInt ; PIN-Change-Interrupt
rjmp Tc0OvfInt ; TC0-Overflow-Interrupt
reti ; EERDY-Interrupt, nicht benutzt
reti ; ANACOMP-Interrupt, nicht benutzt
reti ; TC0COMPA-Interrupt, nicht benutzt
reti ; TC0COMPB-Interrupt, nicht benutzt
reti ; WDT-Interrupt, nicht benutzt
reti ; ADC-Interrupt, nicht benutzt
;
; *****************************************************
; INTERRUPT-SERVICE-ROUTINEN
; *****************************************************
;
; Pin-Change-Interrupt, startet Signal
;
PcInt:
in rSreg,SREG ; Status sichern
tst rDauerL ; Signal schon gestartet?
brne PcIntR ; ja, ignoriere Signal
tst rDauerM ; teste auch MSB
brne PcIntR ; schon gestartet
sbis PINB,bKurz ; Kurzes Signal auf 1?
rjmp PcIntK ; nein, starte kurze Signaldauer
sbic PINB,bLang ; Langes Signal auf 0?
rjmp PcIntR ; kein aktives Signal, ignoriere Int
ldi rDauerM,HIGH(cLSin) ; setze Zaehler auf Lang
ldi rDauerL,LOW(cLSin)
rjmp PcIntS ; Starte Signalausgabe
PcIntK:
ldi rDauerM,HIGH(cKSin) ; starte kurzes Signal
ldi rDauerL,LOW(cKSin)
PcIntS:
ldi rimp,1<<TOIE0 ; starte TC0-Interrupts
out TIMSK0,rimp
sbi PORTB,bTx ; starte Ausgang
PcIntR:
out SREG,rSreg ; Status wieder herstellen
reti ; Zurueck vom Interrupt
;
; TC0-Overflow-Interrupt, tritt bei Erreichen des
; CTC-Wertes auf gibt naechsten Tabellenwert aus
;
Tc0OvfInt:
in rSreg,SREG ; Status sichern
lpm R0,Z+ ; lese Tabellenwert und erhoehe Z
out OCR0B,R0 ; gib an TC0-COMPB weiter
cpi ZL,LOW(2*SinTabEnde) ; Ende der Tabelle?
brne Tc0OvfIntR
ldi ZH,HIGH(2*SinTab) ; an den Anfang der Tabelle
ldi ZL,LOW(2*SinTab) ; zuruecksetzen
sbiw rDauerL,1 ; Anzahl Sinus minus Eins
brne Tc0OvfIntR ; noch nicht, mache weiter
ldi rimp,0 ; stelle Interrupts ab, TC0 macht allein
out TIMSK0,rimp ; mit letzten OCR0B-Wert weiter
cbi PORTB,bTx ; stoppe Ausgang
Tc0OvfIntR:
out SREG,rSreg ; Status wieder herstellen
reti ; Zurueck vom Interrupt
;
; ***********************************************
; HAUPTPROGRAMM
; ***********************************************
;
main:
; Stapel initiieren
ldi rmp,LOW(RAMEND) ; Stapelzeiger auf Ende SRAM
out SPL,rmp
; Taktfrequenz auf 9,6MHz
ldi rmp,1<<CLKPCE ; Clock Prescaler Change Enable
out CLKPR,rmp
ldi rmp,0 ; Teiler auf 1
out CLKPR,rmp
; Port-Ein- und Ausgaenge konfigurieren
ldi rmp,(1<<bPwm)|(1<<bTx) ; OC0B und Tx als Ausgang
out DDRB,rmp ; in Richtungsregister
ldi rmp,(1<<bPwm)|(1<<bKurz)|(1<<bLang)|(1<<bTx) ; Ausgang OC0B
out PORTB,rmp ; und Aktiv auf 1, Pullup auf Eingaenge
; Zaehler zu Anfang auf 38 Sekunden
clr rDauerM
clr rDauerL
; Zeiger Z auf Tabellenanfang
ldi ZH,HIGH(2*SinTab) ; Z auf Sinus-Tabelle
ldi ZL,LOW(2*SinTab)
lpm R0,Z+ ; ersten Wert aus Tabelle lesen
out OCR0B,R0 ; an TC0-COMPB ausgeben
; Timer TC0 einstellen
ldi rmp,cCtc ; CTC auf 171 setzen
out OCR0A,rmp
ldi rmp,(1<<COM0B1)|(1<<WGM01)|(1<<WGM00) ; Fast PWM,
out TCCR0A,rmp ; 0C0B bei Match auf 0, TOP=OCRA
ldi rmp,(1<<WGM02)|(1<<CS00) ; Fast PWM, Prescaler=1,
out TCCR0B,rmp ; Timer starten
ldi rmp,1<<TOIE0 ; TC0-Interrupts ermoeglichen
out TIMSK0,rmp
; Pin-Change-Interrupts einstellen
ldi rmp,(1<<bKurz)|(1<<bLang) ; Bits maskieren
out PCMSK,rmp
ldi rmp,1<<PCIE ; Pin-Change-Int einschalten
out GIMSK,rmp
; Sleep-Mode einstellen
ldi rmp,1<<SE ; Sleep Enable, Mode 0
out MCUCR,rmp
; Interrupts generell einschalten
sei
; Hauptprogramm-Loop
Loop:
sleep ; CPU schlafen legen
nop ; Dummy nach aufwachen
rjmp Loop ; wieder schlafen legen
;
; ***********************************************
; SINUS-TABELLE
; ***********************************************
;
; Sinustabelle fuer Pulsweiten-Modulator
; fuer CTC=171, niedrigster COMPB-Wert=18
;
SinTab:
.DB 94, 109, 123, 136, 148, 157, 164, 169 ; 0..90 Grad
.DB 170, 169, 164, 157, 148, 136, 123, 109 ; 90..180 Grad
.DB 94, 79, 65, 52, 40, 31, 24, 19 ; 180..270 Grad
.DB 18, 19, 24, 31, 40, 52, 65, 79 ; 270..360 Grad
SinTabEnde:
;
; End of source code

http://www.avr-asm-tutorial.net/avr_de/praesentation/sourcecode/bsp11_1750_SinePwm.asm1/20/2009 7:48:34 PM
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Zielsetzung der Beiträge


In den letzten Monaten kommen in vielen Bastelanleitungen Prozessoren des Typs AT90S von
ATMEL (http://www.atmel.com) vor. Sie erfreuen sich also wachsender Beliebtheit insbesondere
auch in Amateur-Kreisen. Woher kommt diese Popularität? Was muss man beachten, wenn man
diese Prozessoren in eigenen Schaltungen nutzen will? Was steckt in diesen schwarzen Kästchen? In
der Serie wird für den Anfänger erklärt, was es mit diesen Chips auf sich hat und wozu sie zu
gebrauchen sind.

Überblick über die Beiträge


Die folgenden Seiten enthalten die Beiträge, die für die Mitgliederzeitschrift des Deutschen Amateur-
Radio-Clubs DARC geschrieben wurden. Hier der Überblick:

1. Teil I: Hardware der AVR-Mikrcontroller


❍ Was ist ein AVR-Prozessor?

❍ Allgemeine elektrische Eigenschaften

❍ Welche AVR-Typen gibt es?

❍ Multifunktionale Pins

❍ Quellen

2. Teil II: Software der AVR-Mikrocontroller


❍ Software selbstgemacht

❍ Assembler mit Editor

❍ Symbole und Instruktionen

❍ Assemblieren

❍ Simulieren

❍ Hilfen zum Lernen

3. Teil III: Programmieren von AVR-Mikrocontrollern


❍ Serielles Programmieren

❍ Programmieren in der Schaltung

❍ Programmieren auf Boards

❍ Programmieren ohne Boards

4. Teil IV: Beispielanwendung AVR-CW-Geber


❍ Aufgabe: Demonstration der Leistungsfähigkeit

❍ Funktionen der Schaltung

❍ Aufbau der Hardware

❍ Aufbau der Software

❍ Bedienung über Einstellmenue

❍ Anhang: Quellcode der Software

Wer die gesamten vier Teile mit allen Grafiken von dieser Webseite auf seinen Rechner laden will,
findet bei diesem Link eine gezippte Datei. Diese sollte mit einem Entpackprogramm ausgepackt
werden. Dabei müssen unbedingt die Pfade im gezippten Archiv beibehalten werden, da sonst
Dateien überschrieben werden.

Besucher auf dieser Seite seit 06.01.2002:

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/index.html1/20/2009 7:48:39 PM
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 1

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Teil I: Hardware von ATMEL-AVR-Mikrocontrollern

Was ist ein AVR-Prozessor?

AVR-Prozessoren sind kleine, fertig aufgebaute Rechner, die schon alles haben, was einen erwachsenen
Computer ausmacht: eine Recheneinheit (CPU), nur-lesbaren-Programmspeicher, statischer Speicher,
nichtflüchtiger und wiederbeschreibbarer Speicher (EEPROM), eine Unterbrechungssteuerung (Interrupts),
den Taktoszillator sowie zahlreiche weitere Hardwarekomponenten wie Parallelports, Timer/Zähler,
asynchrone und synchrone serielle Schnittstellen, Pulsweiten-Modulatoren (Digital-Analog-Wandler),
Analog-Digital-Wandler, Echtzeituhren. Weil alles schon drin ist im Chip und nur noch ein paar wenige
externe Pins zu beschalten sind, sind die externen Beschaltungen sehr einfach.

Typisch für AVR-Prozessoren ist der eingebaute wiederbeschreibbare Programmspeicher. Da kein externes
EPROM nötig ist und der Flash-Speicher im seriellen Übertragungsmodus ohne besondere
Programmierspannung beschreibbar ist, kann der Chip sogar innerhalb der fertigen Schaltung
programmiert werden. Besonders bequem also für den Gelegenheitsprogrammierer, der sich langsam an die
Programmierung herantraut und viele Versuche bis zum Erfolg braucht.

Weil Programmspeicher und etwas RAM-Speicher schon im Chip eingebaut sind, wird nach außen hin
kein Adress- und Datenbus gebraucht. Das macht es möglich, die kleinsten Prozessoren in einem nur
achtpoligen Gehäuse unter zu bringen und stellt die meisten Pins für Ein- und Ausgaben zur Verfügung. In
der Schaltung entfällt die Verdrahtung der Busanschlüsse, das macht die Schaltung einfach und hält die
extern erforderlichen Komponenten in engen Grenzen.

Trotz der 8-bittigen internen Architektur sind die Prozessoren auch bei 8 bis 10 MHz Takt sehr schnell.
Dazu trägt der eigens optimierte Befehlssatz (Reduced Instruction Set, RISC), die 16-bittige
Befehlsarchitektur und der von Speicherzugriffen getrennte interne Zugriff auf den Programmspeicher bei.
Bis auf wenige Ausnahmen braucht jeder Befehl nur einen Taktzyklus und der Zugriff auf den
Programmspeicher erfolgt schon während der Abarbeitung des vorausgegangenen Befehls (Fetch during
execution).

Zeitkritische Anwendungen können die Möglichkeit der Unterbrechung nutzen, so dass die Anforderung z.
B. durch ein Hardware-Ereignis nach optimal kurzer Zeit bearbeitet wird. Zahlreiche Interrupts sind
konfigurierbar, die Bearbeitung gleichzeitig eintreffender Interrupts erfolgt nach einer vorgegebenen
Priorität. Zur Geschwindkeitserhöhung trägt auch die Möglichkeit bei, das interne RAM als
Zwischenspeicher (Stapel, Stack) zu nutzen. Rein interruptgesteuerte Programme können den Chip in den
Schlafmodus versetzen, mit gut halbiertem Strombedarf, und werden auf Anforderung schnell wieder
geweckt.

Allgemeine elektrische Eigenschaften

Die Chips lassen sich mit einer Betriebsspannung zwischen 4 und 6 Volt betreiben, manche
Ausführungsformen auch mit 2,7 bis 6 Volt. Sie brauchen bei 8 MHz Takt und 5 Volt Betriebsspannung
zwischen 10 und 12 mA. Im Schlafmodus mit Weckfunktion sinkt der Verbrauch auf weniger als die
Hälfte. Auch eine niedrigere Betriebsspannung und eine niedrigere Taktrate spart Strom. Sie sind also recht
sparsam zu betreiben.

Beim Hochfahren der Betriebsspannung wird ein Power-On-Reset durchgeführt, die Hardware wird auf
Anfangswerte zurückgesetzt und die Programmbearbeitung beginnt bei Adresse 0000. über einen externen
Resetpin kann ein Neustart ebenfalls ausgelöst werden.

Der Takt kann an zwei Pins extern über einen Quarz oder Keramikschwinger erzeugt werden. Er kann aber
auch aus einem eigenständigen externen Generator zugeführt werden. Die Taktung mit einem internen RC-
Generator ist ebenfalls möglich, allerdings ist die Taktfrequenz dann sehr abhängig von der
Betriebspannung und der Temperatur.

Pins, die als Ausgabeports konfiguriert sind, können je nach Betriebsspannung zwischen 10 und 20 mA
treiben, so dass z.B. LEDs über einen Strombegrenzungswiderstand direkt gegen die Betriebsspannung
getrieben werden können.

Die Abbildung 1 (Anzeige als PDF-Datei) zeigt einen der einfachsten AVRs in seiner Außenbeschaltung.

Die RC-Kombination am Reseteingang verzögert den Reset beim Hochfahren der Betriebsspannung, der
Widerstand vor dem Reseteingang begrenzt den Strom aus dem Elko in den Pin insbesondere beim
Abschalten der Betriebsspannung, die Diode sorgt für einen sicheren Reset beim kurzen Absenken der
Betriebsspannung. Der Kondensator am Betriebsspannungsanschluss glättet die Schaltspitzen, die durch
die Taktung im Chip entstehen und sorgt für weniger HF auf der Versorgungsleitung. Der Taktoszillator ist
mit einem Standardquarz bestückt, die beiden Kondensatoren helfen beim Anschwingen des internen
Oszillators.

Welche AVR-Typen gibt es?

Die AVR-Typen unterscheiden sich hinsichtlich des verfügbaren Speichers (z.B. von 2k bis 8k), der nach
außen hin verfügbaren Ein- und Ausgabepins (z.B. 3 bis 48 Pins) und der eingebauten
Hardwarekomponenten. Drei beliebte Typen sind in der Tabelle 1 charakterisiert.
Tabelle 1: Ausgewählte AVR-Typen und ihre Charakteristika
AVR-Typ AT90S2323 AT90S2313 AT90S8515
Anschlusspins 8 20 40
max. Taktrate MHz 8 10 8
Programmspeicher K Words 2 2 8
Statisches RAM Bytes 128 128 512
EEPROM-Speicher Bytes 128 128 512
Ein-/Ausgabe-Pins 3 15 32
Wer noch mehr I/O-Pins oder Speicher braucht, wird bei den AT-MEGA-Typen fündig, die es allerdings
nur in besonderen Gehäuseformen gibt.

Die eingebauten Hardwarekomponenten dieser drei vorgestellten Typen sind in der Tabelle 2 aufgelistet.
Tabelle 2: Die Hardwarekomponenten ausgewählter AVR-Typen
AVR-Typ AT90S2323 AT90S2313 AT90S8515
8-Bit-Timer 1 1 1
16-Bit-Timer/Counter - 1 1
Async. (UART) - 1 1
Pulsweitenmodulator (PWM) - 1 2
Analogvergleicher(AnaComp) - 1 1
Wer synchrone serielle Schnittstellen, Analog-Digital-Wandler oder Real-Time-Clocks braucht, wird bei
den anderen Typen der Serie fündig.

Multifunktionale Pins

Typisch ist, dass die Ein- und Ausgabepins verschiedene Aufgaben übernehmen können, je nachdem
welche Hardwarekomponenten per Software aktiviert werden. Sie können einfache Ein- oder Ausgabe-
Ports bilden. Wenn sie als Eingabepins geschaltet sind, kann ein Pull-Up-Widerstand softwaremäßig
zugeschaltet werden. über einige Ein- und Ausgabepins erfolgt die serielle Programmierung des Programm-
Flash-Speichers (SCK, MOSI und MISO genannt), wenn der Reset-Pin aktiviert ist. Die Doppelfunktion
der Pins ist in Abbildung 2 ( Anzeige als PDF-Dokument) am Beispiel des 20-poligen 2313 gezeigt.

Pins, die für die interne Funktionalität benötigt werden, stehen als allgemeine Ein- und Ausgabe-Pins nicht
mehr zur Verfügung. Die Planung der Beschaltung des AVR sollte daher von Anfang an diese benötigten
Funktionen berücksichtigen. Zur Not muss der nächstgrößere Typ herhalten, wenn die Funktionalität oder
die Zahl der I/O-Pins nicht mehr ausreicht.

Quellen

Wer Schaltungen entwirft (und die Software dafür schreiben will), braucht dringend die Datenblätter der
Typen vom Hersteller. Dort ist genau beschrieben, wie die Pins zu beschalten sind, welche
Timinganforderungen zu beachten sind, usw. Die Datenblätter für alle Typen kriegt man von der
Internetseite des Herstellers (http://www.atmel.com, dort 8-Bit-RISC AVR auswählen).

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil1/index.html1/20/2009 7:48:46 PM
+5V
10 nK

8 7 6 5
VCC PB2 PB1 PB0

+5V
AT 90 S 2323
1N4148 RESET XTAL1 XTAL2 GND
100k
1 2 3 4
1k
4MHz
+
1µT 27pK 27pK
20 11
VCC PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 PD6
SCK MISO MOSI AIN1 AIN0
Serial Prog. AnaComp
OC1 ICP
AT90S2313 Outp.Comp.Match Inp.Comp.

UART Ext.Int. Timer Clock


RxD TxD INT0 INT1 T0 T1

XTAL
RESET PD0 PD1 2 1 PD2 PD3 PD4 PD5 GND
1 10
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 2

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Teil II: Software von ATMEL-AVR-Mikrocontrollern

Software selbstgemacht

Weil AVR-Prozessoren für eine ganz bestimmte Hardware eingesetzt werden sollen, ist die Software
auf die Hardware-Umgebung eng anzupassen. Das setzt voraus, dass die Software speziell für die
gewählte Schaltung geschrieben wird. Wer so hardware-nah noch nie programmiert hat, wird zu
Beginn eine größere Mühe haben, wenn er sich an die Programmierung erst langsam gewöhnen muss.

Das wird auch kaum einfacher, wenn man statt der Assemblersprache in C oder in Basic
programmiert. Das hat zwar den Vorteil, dass man ein paar Sprachelemente schon kennt, aber so
richtig hardware-nah kommen Hochsprachen nicht ran. Wer die Fähigkeiten optimal ausreizen will,
sollte sich der Mühe unterziehen, Assembler zu lernen. Mit den AVR ist das besonders erleichtert,
weil man den Prozessor in der Schaltung selbst erproben kann und weil es einige einfache Werkzeuge
gibt, die Abläufe auf dem Trockenen zu testen.

Hier werden nur einige Grundbegriffe der Softwareentwicklung für AVRs behandelt. Es gibt
zahlreiche umfangreiche Hilfen, vom Buch bis zum Internet. Die werden am Ende kurz besprochen.
Wie das fertig assemblierte Programm in den Chip kommt, erklärt der nächste Teil dieser Serie.

Assembler mit Editor

Assembler programmieren ist zunächst das Schreiben von reinem Text in eine reine Textdatei. Die
folgenden Zeilen versetzen die acht Anschlusspins von Port B in einem AVR vom Typ AT90S2313
in den lesenden Zustand (alle Pins sind Eingänge) und schalten 10k-Pull-Up-Widerstände an diese
Eingänge. Beim Lesen sollten also alle Eingänge eine logische Eins zeigen.

(=> Screenshot mit dem Beispielprogramm im AVR-Editor wavrasm von ATMEL) Dieser lesbare
Text wird in einer Textdatei gespeichert. Er ist als solches noch nicht brauchbar für den AVR. Erst
nach dem Übersetzen mit einem Assembler wird daraus ein maschinen-verständliches Programm, das
in den Chip gefüttert werden kann.

Als Editoren eignen sich sehr einfache Programme (z.B. Notepad für Windows oder KWrite für
Linux) oder spezielle Editoren wie der von ATMEL verfügbare Assemblereditor wavrasm, der Editor
im Studio von ATMEL bzw. der sehr schön gestaltete AVR-Assembler-Editor von Tan Silliksaar.
Spezielle Editoren für AVR-Assembler erkennen z.B. die Instruktionen oder prüfen während der
Eingabe nach, ob ein Symbol schon definiert ist und färben die Wörter dann anders ein. Auf diese
Weise findet man schneller Schreibfehler (das sind ca. 95% der Fehler in Assembler; die
verbleibenden 5% sind Denkfehler und viel schwerer zu finden).

(=> Screenshot eines Programmes mit dem ATMEL Studio-Editor)

(=> Screenshot mit dem Beispielprogramm im AVR-Editor von Tan Silliksar)

Symbole und Instruktionen

Der Text ist trotz der Erläuterungen, die immer mit einem Semikolon beginnen, aber auch so kaum
lesbar. Deshalb gibt es die Möglichkeit, statt der hexadezimalen Zahlen und der Konstruktion R16
auch zu schreiben:

; Beispielprogramm in Assembler, leserlicher


;
; Definitionen
.EQU PORTB = $18
.EQU DDRB = $17
.EQU PINB = $16
.DEF MeinRegister = R16
; Programm
clr MeinRegister
out DDRB,MeinRegister
ser MeinRegister
out PORTB,MeinRegister
in MeinRegister,PINB
;
; Ende des leserlichen Programmes

Der Assembler versteht also Symbole. Symbole (PORTB) sind für Menschen etwas leichter zu
merken als Hexadezimalzahlen ($18). Allerdings muss dem Assembler das alles erst mitgeteilt
werden (mit .EQU), von selbst weiss er das nicht. Dass PORTB die Ein- und Ausgabepins PB0 bis
PB7 am AVR meint, muss der hardwarenahe Programmierer erst mal wissen. Dass DDRB das
Datenrichtungsregister von Port B meint, auch. Wenn man dort Nullen (clr MeinRegister steht für
CLEAR und bedeutet, dass alle acht Bits im Register zu Null gesetzt werden) hinschreibt, dann sind
alle Ausgangstreiber an diesen Pins ausgeschaltet. Wenn man dann noch Einsen nach PORTB
schreibt (ser MeinRegister steht für "SET Register" und setzt alle Bits im Register auf 1), sind die
Pull-Up-Widerstände eingeschaltet und ziehen die Eingänge auf logisch 1. Wenn nun noch die
Eingänge des Ports (PINB) eingelesen werden (in), dann hat MeinRegister anschliessend den Wert
1111.1111 binär, $FF in hexadezimal oder 255 in dezimal.

Mit diesem großartigen Programm, das man im Quelltext über diesen Link downloaden kann, kann
man bis dahin nur wenig anfangen, es zeigt aber folgendes:

1. Ob ein Pin sich als Eingang oder als Ausgang verhält, hängt alleine davon ab, was das
Programm gerade einstellt. Das kann auch im Programmablauf wechseln, wenn man
bidirektionale Ports braucht.
2. Alle Hardware wird in sogenannten Ports kontrolliert. Das sind Speicher, die in Abhängigkeit
von ihrem Inhalt das gesamte Verhalten der Hardware bestimmen.
3. ähnlich wie die Eingangs- und Ausgangspins lassen sich asynchrone Schnittstellen,
Analogvergleicher, u.v.a.m. vom Programmierer ein- und ausschalten oder sonstwie
kontrollieren.
4. Ein Assemblerprogramm kann mit Symbolen zwar etwas leserlicher gestaltet werden, aber die
Prozessorinstruktionen (hier: clr, out, ser und in) lassen sich nicht ersetzen. Sie sind Symbole
derjenigen Befehlsabläufe, die im Prozessor fest vorgegeben sind. Die muss man halt
nachschlagen oder auswendig lernen.

Assemblieren

Das Übersetzen von Symbolen in hexadezimale Zahlenwerte und das Übersetzen von Instruktionen
in binäre Bitfolgen erledigt der Assembler.

(=> Screenshot: Aufruf des Assemblers mit dem Beispielprogramm)

Der Assembler ist ein Programm, das unsere Textdatei BEISPIEL.ASM als Futter kriegt und dafür
eine Reihe neuer Dateien ausspuckt:

1. BEISPIEL.HEX: Diese Datei enthält die Bitfolge für den Prozessor, codiert im sogenannten
Intel-Hex-Format. Das ist auch mit einem Texteditor lesbar, aber darf unverstanden bleiben.
Damit wird anschließend die Programmiersoftware gefüttert, die versteht das. (=> Screenshot:
Assembliertes Assemblerprogramm im Intel-Hex-Format)
2. BEISPIEL.LST: Diese Datei enthält zusätzlich zu dem eingegebenen Text auch die
hexadezimale Übersetzung desselben in Instruktionen für den Prozessor. Die kann man
ansehen, muss man aber nicht. (=> Screenshot: Gelistetes Assemblerprogramm nach dem
Assemblieren)
3. BEISPIEL.OBJ: Diese Datei wird benötigt, um das Programm zu simulieren. Das kommt
jetzt gleich dran. Sie ist nur maschinenlesbar.

Simulieren

Oft muss man einen komplexen Ablauf programmieren. Dann lohnt es sich, diesen Ablauf in
Päckchen zu programmieren und die einzelnen Päckchen auf dem Trockenen zu erproben. Das
Trockendock für AVR Assembler heißt Studio und wird von ATMEL kostenlos zur Verfügung
gestellt.

Das Studio wird mit der Object-Datei gefüttert, ein Zielchip ausgewählt und seine Taktfrequenz
vorgewählt. In dem erscheinenden Quelltext von Beipiel.asm lassen sich sogenannte Breakpoints
setzen. Dann wird der Ablauf entweder im Einzelschrittverfahren oder mit "Go" gestartet. Nach
jedem Schritt bzw. bei Erreichen eines Breakpoints bleibt der Ablauf stehen. Jetzt können in Ruhe
Register oder Ports auf ihren Inhalt hin untersucht werden. Im Prozessor-View kann die abgelaufene
Zeit abgelesen werden, der Inhalt der Prozessorflags kann inspiziert werden, usw.

(=> Screenshot: Das Beispielprogramm im Studio nach Bearbeiten der ersten beiden Instruktionen)

Nach Bearbeiten der ersten vier Befehle hat sich am Registerinhalt von R16 und beim Port B etwas
getan. Im Studio wird mit Rot die Aufmerksamkeit des Simulierers erregt.

(=> Screenshot: Das Beispielprogramm nach Bearbeiten der ersten vier Instruktionen)

Selbstverständlich kann der Inhalt von Registern oder von Port-Bits manuell geändert werden, wenn
man bestimmte Reaktionen der Software provozieren will. Es gibt noch viele weitere
Manipulationsmöglichkeiten, auf die hier nicht im Detail eingegangen werden soll. Damit stehen
mächtige Werkzeuge zur Verfügung, mit denen sich erste Schritte machen lassen.

Hilfen zum Lernen

Hilfen zum Erlernen der Assemblersprache gibt es in Büchern oder im Internet. Bücher haben den
Nachteil, dass sie wegen der beschränkten Klientel teuer sind und rasch veralten. Im Internet gibt es
zahlreiche Beispiele für AVR-Assemblerprogramme. Eine recht gute Sammlung in englisch führt
Kanda Systems (http://www.avr-forum.com). über 100 meist englisch-sprachige AVR-
Programmierer haben sich im AVR-Webring ( http://R.webring.com/hub?ring=avr&list)
zusammengeschlossen, einer Linksammlung mit vielen Beispielen. Gut bestückte und gepflegte
deutschen Linksammlungen zum Thema haben http://www.mikrocontroller.net/links.htm und http://
www.lug-kiel.de/links/micros.html. Speziell für den blutigen Anfänger in Sachen Bits und Ports mit
ausführlichen Erläuterungen ist die Webseite http://www.avr-asm-tutorial.net gemacht. Die Seite ist
zweisprachig. Der Autor freut sich über zusätzlichen Verkehr auf seiner Seite.

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil2/index.html1/20/2009 7:48:51 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/ATMEL.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/ATMEL.gif1/20/2009 7:48:53 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIOED.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIOED.gif1/20/2009 7:48:55 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/SILLIKS.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/SILLIKS.gif1/20/2009 7:48:57 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/beispiel.asm

; Beispielprogramm in Assembler, fast unleserlich


;
clr R16
out $17,R16
ser R16
out $18,R16
in R16,$16
;
; Ende des fast unleserlichen Beispielprogrammes

http://www.avr-asm-tutorial.net/cq-dl/teil2/beispiel.asm1/20/2009 7:48:58 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/ASSEMBLE.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/ASSEMBLE.gif1/20/2009 7:49:00 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/IHEX.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/IHEX.gif1/20/2009 7:49:01 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/LIST.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/LIST.gif1/20/2009 7:49:03 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIO1.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIO1.gif1/20/2009 7:49:08 PM
http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIO2.gif

http://www.avr-asm-tutorial.net/cq-dl/teil2/STUDIO2.gif1/20/2009 7:49:14 PM
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 3

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Teil III: Programmieren von ATMEL-AVR-Prozessoren


Nach dem Entwurf der Schaltung und nach dem Schreiben und Testen der Software im Simulator
muss nun der binäre Code in den AVR chip. Jeder AVR verfügt als Programmspeicher über eine
gewisse Menge Flash Memory, das sich programmieren und jederzeit wieder elektrisch löschen und
wiederbeschreiben lässt. Es gibt grundsätzlich zwei Möglichkeiten zur Programmübertragung in den
Flash-Speicher: serielles oder paralleles Programmieren.

Serielles Programmieren

Für professionelle Herstellung ist paralleles Programmieren von Vorteil. Die einfachste Form des
Programmierens, und damit die erste Wahl des Amateurs, ist das serielle Übertragen in den
Programmspeicher. Serielles Programmieren bedeutet, dass die Programmbits nacheinander,
gesteuert durch einen von außen angelegten Takt am Pin SCK, über den Pin MOSI in ein internes
Schiebregister eingeschoben und von dort in das Flash Memory kopiert werden. Damit der
Programmiervorgang beobachtet, nach Abschluss verifiziert und der Inhalt des Flash gelesen werden
kann, ist ein Datenausgang MISO vorhanden. Beim Programmieren werden also drei Signalleitungen
benötigt: der Takt SCK, die Eingabedaten MOSI und die Ausgabedaten MISO. Damit dafür nicht
extra drei Pins verloren gehen, wechseln drei Pins beim Reset ihre Funktion. Ist Reset aktiv, werden
sie mit dem seriellen Programmier-Interface verbunden. Der Programmiermodus wird aber erst dann
aktiv, wenn ein entsprechendes Befehlswort eingeschoben wird.

Programmieren in der Schaltung

Bemerkenswert ist dabei, dass das serielle Programmieren weder für das Löschen noch für den
Programmiervorgang erhöhte Spannungen benötigt. Man kann daher das Programmieren in der
Schaltung selbst durchführen. Allerdings ist dabei zu beachten, dass die dafür drei benötigten Pins
entweder

a. nur für diesen Zweck vorbehalten sind,


b. über Widerstände von mindestens 1 k von der Restschaltung abgetrennt werden, oder
c. über eine Multiplexschaltung nur bei aktivem Reset mit dem Programmiersignal verbunden
werden.

Diese Beschaltung wird als ISP (In-System-Programming) bezeichnet. Die zwei Möglichkeiten b)
ohne Multiplexer und c) mit Multiplexer werden im Schaltbild dargestellt (PDF-Version des
Schaltbildes).

Die Möglichkeit b. ist einfach zu verstehen: die Programmierimpulse liegen parallel zur
Schaltungselektrik an. Das geht natürlich nur, wenn über die Schutzwiderstände nicht allzu hohe
Ströme angefordert werden und wenn die Schaltung selbst auf die wilden Programmierimpulse nicht
allergisch reagiert.

Bei der dargestellten Möglichkeit c) ist der AVR mit den auch zur Programmierung verwendeten
Pins mit der Schaltung verbunden, wenn /Reset auf High liegt. Aktiviert das Programmiergerät den /
Reset-Eingang, werden die Programmierpins mit dem Programmierstecker verbunden und die
Programmierung kann erfolgen. Hierbei sind die Ströme auf die entsprechenden Grenzbelastungen
des Multiplexers begrenzt. Die Programmierpulse können hier nicht stören.

Programmieren auf Boards

Der dargestellte ISP-Header ist identisch mit der Beschaltung des 10-poligen ISP-Headers am
STK200 und am STK500 von ATMEL. Der vom STK200 bekannte Stecker vom Parallelport des
Rechners kann hier direkt aufgesetzt werden, vom STK500 gibt es eine ähnliche Verbindung.

Für den Anfänger ist es am einfachsten, sich ein solches Programmierboard zu besorgen und damit zu
beginnen. Man braucht sich dann nicht erst mit Hardware herum zu beißen und kann sofort mit dem
Programmieren und Testen loslegen. Die Boards STK500 und STK200 haben eine LED-Reihe und
Taster, die eine einfache Ausgabe von Zwischenergebnissen oder eine Eingabe von den Tastern
ermöglichen.

Beim STK200, das nicht mehr im Handel zu bekommen ist, erfolgte der Anschluss an den Rechner
über einen freien Parallelport. Das stößt in der Regel auf Probleme, weil da schon der Drucker
dranhängt. Echte Freaks besorgten sich für ein paar Mark eine Zusatzkarte mit einem Parallelport für
den PC, aber die kostete auch wieder einen wertvollen Interrupt.

Das ist beim STK500 anders, weil das Board einen intelligenten Prozessor mit Speicher und seriellem
Interface hat. Dieses Interface wird mit einem freien seriellen Anschluss am PC verbunden. Die
Software zum Übertragen des Programmes zum Board ist in den neueren Studio-Versionen enthalten.
Auch die Programmierung erfolgt über das Studio.

( => Screenshot: Das Programmierinterface im Studio bedient ein STK500 board)

Mit dem STK500 ist es neben dem seriellen Programmieren auch möglich, die Chips parallel und mit
einer erhöhten Spannung (12 Volt) zu programmieren. Dadurch kommt man an speziellere
Einstellungen in den Chips heran. die beim seriellen Programmieren nicht zugänglich sind. Bei
bestimmten AVR-Typen lassen sich Oszillator-Optionen oder Schutzeinstellungen auf diese Art
brennen. Wir legen das erst mal in die Ecke für Fortgeschrittene ab.

Die Software zum Programmieren über die ISP-Verbindung bzw. des STK200- und STK500-Boards
gibt es kostenlos auf der Webseite von ATMEL.

Programmieren ohne Boards

Wer kein STK500 kaufen will, muss sich die Hardware selbst bauen. Am einfachsten und günstigsten
kommt der Eigenbau eines Parallelport-Headers, wie er beim STK200 mitgeliefert wurde. Die
Schaltung ist sehr einfach, außer einem leicht erhältlichen Treiber-IC braucht es nur Verbindungen
und Stecker. Dieses und andere Programmiergeräte finden sich bei

( http://www.lug-kiel.de/links/details/f_avr.html#microp)

Es gibt zahlreiche mehr oder weniger komplizierte Programmiergeräte für den Eigenbau. Die
komplizierteren haben allerdings das typische Henne/Ei-Problem: sie erfordern schon ein
Programmiergerät, damit man den Prozessor des Programmiergeräts mit der Programmier-Software
programmieren kann.

Viel Erfolg beim Selberstricken.

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil3/index.html1/20/2009 7:49:18 PM
ISP-Header
11 10 9 6 7
MISO 12 A B C INH VEE 13
X0 X1
Zur
SCK 2 1 Schal-
Y0 Y1

RESET 5
Z0
74HC4053 Z1
3
tung

VCC X Y Z GND
PROG 16 14 15 4 8
MOSI

AVR AVR
b) c)

Zur Schaltung
http://www.avr-asm-tutorial.net/cq-dl/teil3/STK500PR.gif

http://www.avr-asm-tutorial.net/cq-dl/teil3/STK500PR.gif1/20/2009 7:49:23 PM
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 4

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Teil IV: Applikation CW-Geber


Dieser Beitrag beschreibt einen CW-Geber mit einem AVR Mikroprozessor des Typs AT90S2313.
Damit sollen die vielfältigen Hardware- und Software-Fähigkeiten demonstriert werden, die diese
Prozessoren für den anspruchsvollen Bastler haben können.

Wer ein STK200- oder STK500-Programmierboard besitzt, kann auf den Bau der Hardware
weigehend verzichten und die Software für das entsprechende Board direkt verwenden (siehe Betrieb
mit Board).

Aufgabe: Demonstration der Leistungsfähigkeit von Hard- und Software

Die Beschaltung des Prozessors demonstriert, wie die interne Hardware mit wenigen externen
Komponenten für die Lösung einer recht komplexen Aufgabe genutzt werden kann. Der interne 16-
Bit-Timer wird zur exakten Erzeugung der Niederfrequenz verwendet. Die Hardware lehrt ferner, wie
ein RS232-Interface zur Kommunikation mit der Mikroprozessor-Software realisiert werden kann.
Diese Kommunikation erfolgt zudem mit einem Hardware-Protokoll gesteuert. Das Beispiel zeigt
auch, wie der Mikroprozessor in der fertigen Hardwareschaltung programmiert werden kann.

Softwareseitig kann an dem Beispiel demonstriert werden, wie die interrupt-gesteuerte


Kommunikation mit der RS232-Schnittstelle und der Timer-gesteuerten NF-Erzeugung funktioniert.
Ferner wird in Rechenpausen der stromsparende SLEEP-Betrieb des Prozessors verwendet. Die
programminterne Ablaufsteuerung und die Kommunikation der internen Abläufe miteinander erfolgt
im wesentlichen über ein Flagregister. Als weitere Software-Besonderheiten sind die Multiplikation
und Division von binären Ganzzahlen zu nennen. Schließlich ist in der kleinen Steuerung auch ein
komfortables User-Interface enthalten, das die Einstellung der wichtigsten Eigenschaften der CW-
Ausgabe erlaubt.

Insgesamt fördert dieses Stück Software wegen der Komplexität und Unübersichtlichkeit kaum das
Verständnis beim blutigen Anfänger. Einzelne Teile können aber gerne von dieser Vorlage
abgekupfert und für den eigenen Gebrauch umgebogen werden oder als Anregung dienen.

Natürlich soll das Ding für den eigentlichen Zweck, das Geben von Morsezeichen, brauchbar sein.
Irgendwann lerne auch ich die damit mal.

Funktionen der Schaltung

Die fertig aufgebaute und programmierte Schaltung gibt ohne angeschlossenen PC beim Einschalten
einen Text in CW mit festgelegter Geschwindigkeit und Tonhöhe aus. Mit einem über die serielle
Schnittstelle angeschlossenen PC und einem dort laufenden Terminalprogramm (z.B. Hyperterminal
für Windows) kann nach Ausgabe des gespeicherten Textes zeilenweise Text eingegeben und in CW
wieder ausgegeben werden. In Maßen kann während der Ausgabe schon weiter Text eingegeben
werden.

Mit dem Terminalprogramm kann auch eine vorgefertigte Textdatei an die Schaltung geschickt
werden, die mehrzeilige Texte enthält. Dabei sorgt das Hardware-gesteuerte RS232-Protokoll dafür,
dass keine Zeichen verloren gehen, da die Textübergabe immer schneller erfolgt als die Ausgabe der
Zeichen in CW.

Mit dem Terminalprogramm kann man nach Eingabe von ESCAPE ferner die eingestellten Werte für
die erzeugte NF-Frequenz, die Gebegeschwindigkeit und den beim Reset auszugebenden Text ändern
und die verstellten Werte im internen EEPROM ablegen. Die Einstellung erfolgt komfortabel
menuegesteuert.

Aufbau der Hardware

Der gesamte Hardware-Aufbau ist recht einfach. Der Aufbau ist im Schaltbild zu sehen.

Schaltbild im GIF-Format
Schaltbild im PDF-Format

Im Zentrum steht der beliebte, leicht erhältliche und preiswerte 20-polige AVR-Prozessor vom Typ
AT90S2313-10P. Als Taktgeber wurde ein vorhandener Quarz mit 10 MHz gewählt, die Hard- und
Software funktioniert aber auch noch mit wesentlich geringerer Taktfrequenz, ab 1 MHz aufwärts.
(Bei anderen Taktfrequenzen muss nur ein Parameter in der Software geändert werden.) Die
Hardware für den Prozessor-Reset ist ebenfalls einfach gehalten, weil mit der Schaltung ja keine
Bremsen für eine Straßenbahn gesteuert werden sollen, bei der Spikes auf der Versorgungsspannung
sicherheitshalber zur Auslegungsgrundlage gehören würden.

Die Ausgabe der NF erfolgt am Port-Pin PB3. Das ist mit Bedacht gewählt, da dieser Pin
softwaregesteuert auch als Ausgabe-Pin OC1 des 16-Bit-Timers verwendet werden kann. Die
Anschaltung des Lautsprechers über eine einfache Gleichstromtrennung ist sehr einfach, aber etwas
hart. Zur Lautstärkeeinstellung wäre statt des 470-Ohm-Widerstandes noch ein Poti angebracht, für
echte Anwendungen wie z.B. die Ansteuerung einer AM/FM/SSB-Sendeanlage noch geeignete RC-
Netzwerke zur Abrundung der Rechteckflanken.

Das RS232-Interface zur Kommunikation mit dem PC ist mit einem MAX232 aufgebaut, der zu den
vier V24-Treibern auch noch die Spannungserzeugung aus 5V enthält. Die Beschaltung des 9-poligen
Steckers ist zur Verwendung eines Nullmodem-Kabels ausgelegt, bei dem die Sende-/Empfangs- und
die RTS-/CTS-Leitung zur Verbindung zweier PCs über die COM-Schnittstelle gekreuzt sind.
Verwendet man stattdessen ein Parallel- oder 1:1-Kabel, muss die Vertauschung schon in der
Schaltung erfolgen (vertauschen von RD/TD und RTS/CTS). Die beiden Jumper Data und Control
ermöglichen in der Stellung Loop den Test von Verbindungskabeln, Steckern und MAX232 ohne
jede Mitwirkung des Prozessors und sind für den manuellen Aufbau hilfreich. Sie können auch
entfallen, wenn man diese Diagnosemöglichkeit nicht braucht.

Für das Experimentieren mit der Software im 2313 ist das ISP-Interface ideal geeignet, da man damit
den Chip mit immer neuen Softwareversionen beschicken kann, ohne ihn aus der Schaltung heraus
nehmen zu müssen. Da an Port-Bits in dieser Schaltung kein Mangel besteht, sind die Portbits PB5
(MOSI), PB6 (MISO) und PB7 (SCK) ausschließlich für diesen Zweck reserviert und Maßnahmen
zur Umschaltung zwischen Normalbetrieb und In-System-Programmierbetrieb können entfallen. Das
Programmier-Interface eignet sich zur Anschaltung an die entsprechende 10-polige Schnittstelle auf
dem ATMEL Board STK500, zur direkten Verbindung mit der Parallel-Schnittstelle über das
KANDA-Interface, das mit dem STK200 mitgeliefert wird, oder auch einem selbst gebauten ISP-
Interface. Die Programmier-LED kann zur Not auch weggelassen werden.

Die Stromversorgung mit 5V ist einfach und kann zur Not auch mit einer kleinen Batterie erfolgen.
Wenn keine weitere Hardware versorgt werden soll, reicht auch ein 78L05 völlig aus.

Aufbau der Software

Die Software für die Selbstbauversion (ohne Programmierboard) kann in verschiedenen Versionen
angezeigt und heruntergeladen werden, sie ist in AVR-Assembler geschrieben. Sie umfasst
ausführlich kommentiert ca. 1100 Textzeilen und ergibt assembliert ca. 650 Worte Programm und ca.
360 Worte an Konstanten (Morsecode-Tabelle, Texte zur menuegesteuerten Kommunikation).
Insgesamt ist der verfügbare Programmspeicher im 2313 (1 k Worte) damit zu 97% ausgelastet. Zur
korrekten Übersetzung ist die von ATMEL verfügbare Headerdatei 2313def.inc erforderlich.

Alle wichtigen Parameter können im Kopf der Software frei eingestellt werden, so dass die
Anpassung bei geänderter Hardware keine großen Probleme verursachen dürfte. Beim Umschreiben
der Software für größere Prozessoren (z.B. AT90S8515) ist darauf zu achten, dass einige
Zeigeroperationen wegen des größeren verfügbaren SRAM- und EEPROM-Bereichs zusätzliche
Änderungen im Code brauchen, damit die 16-Bit-Zeiger richtig funktionieren (z.B. beim Lesen und
Schreiben des EEPROM-Speichers). Das betrifft auch andere Taktraten, Interrupt-Vektoren, den
SRAM-Stapel, etc. An den 8515 angepasste Versionen sind Anhang enthalten.

Morsecodes

Alle Morsecodes der ASCII-Zeichen 32 bis 95 sind in einer Tabelle im Programm abgelegt.
Kleinbuchstaben werden durch Abziehen von 32 in Großbuchstaben umgewandelt. Jedes Zeichen
benötigt ein Byte mit dem Code (Punkt=0, Strich=1), von höherwertigen zu niederwertigen Bits
organisiert, und ein Byte mit der Anzahl Punkte/Striche des jeweiligen Zeichens. Undefinierte
Zeichen werden mit einem Fragezeichen ausgegeben, sie haben die Anzahl Punkte/Striche Null.
Beim Leerzeichen sorgt ein gesetztes siebtes Bit für eine Stummschaltung des NF-Ausganges.

In dieser Tabelle kann der CW-Purist beliebig herumtoben und umbelegen. Das kommt für einige
Sonderzeichen infrage, insbesondere für Belegung der folgenden Codes.

ASCII Morse
-----------
! Warten
# ñ
$ á, å
% é
& (frei)
* (frei)
+ Spruchende
< Verkehrsanfang
> Verkehrsende
@ ch
[,{ ä
\,~ ö
],} ü
^ Irrung

Interruptsteuerung

Besonderheiten des Programmes liegen in dem überwiegend interruptgesteuerten Ablauf. Über eine
entsprechende Vektortabelle wird der Empfang von Zeichen über die serielle Schnittstelle (nicht bei
Menuebetrieb!) und die Timer-Interrupts zur Erzeugung der korrekten Anzahl NF-Pegelwechsel in
Abhängigkeit von der Gebegeschwindigkeit auf die beiden entsprechenden Interrupt-Service-
Routinen verteilt. Der Prozessor selbst befindet sich beim Interrupt-Betrieb die meiste Zeit im
stromsparenden SLEEP-Modus und wird nur durch Hardware-Interrupts aufgeweckt. Die Übergabe
von Senden und Empfang erfolgt über entsprechende Registerflag, das nach jedem Aufwecken
überprüft wird, und den Ablauf in die entsprechenden Routinen verzweigt. Wegen des erheblichen
Zeitbedarfs und der Komplexität des Ablaufes ist der Menuebetrieb nicht innerhalb der
Interruptsteuerung angesiedelt, er erfolgt durch Polling an der UART-Schnittstelle.

Rechenroutinen

Wichtig sind die eingebauten Rechenroutinen zur Multiplikation und Division von 32-Bit-
Binärzahlen. Sie dienen der Umrechnung vom Prozessor- und Timer-Takt in die der NF-Frequenz
angepassten 16-bittigen Compare-Match-Zahl des NF-Timers und der Berechnung der Anzahl von
Interrupts zur Erzielung der richtigen Dauer von Punkten und Strichen, abhängig von der
eingestellten NF-Frequenz und der Gebegeschwindigkeit. Da diese beiden Eingangsgrößen
verstellbar sind, müssen nach jeder Verstellung diese Rechenroutinen bemüht werden, um die
Steuerung anzupassen. Achtung: diese Routinen funktionieren nur innerhalb von besonderen
Wertebereichen und sind nicht ohne weiteres auf andere Wertebereiche von Binärzahlen anwendbar.
Der Rechenmechanismus der Multiplikation (16-bit mal 16-bit binär) und der Division (32-bit durch
16-bit binär, 32-bit durch 8-bit binär) ist aber erkennbar und leicht auf andere Rechenaufgaben
übertragbar.

Steuerung des Hardware-Protokolles

Ungewöhnlich ist die Steuerung der seriellen Schnittstelle zum PC mit dem RTS/CTS-Hardware-
Protokoll. Die Schaltung signalisiert dem PC über die CTS-Leitung, ob sie empfangsbereit für
weitere Zeichen ist. Diese Steuerung ist notwendig, wenn ganze Textdateien übertragen und
ausgesendet werden sollen. Dabei reichen die intern vorhandenen 128 Bytes SRAM zur
Zwischenspeicherung der gesamten Datei nicht aus (ein Teil des SRAM wird zudem für den Stack
benötigt), die Übertragung muss entsprechend dem Ausgabefortschritt abgebremst werden.

Deshalb enthält sowohl die Timer-Ausgaberoutine als auch die UART-Empfangsroutine


entsprechende Prüfungen, ob der verfügbare Pufferbereich zum Empfang weiterer Zeichen ausreicht
und setzt die CTS-Leitung dementsprechend auf aktiv oder inaktiv. Auf diesen Teil (und auf die
entsprechenden Leitungen und andere Beschaltungen) kann verzichtet werden, wenn ein
entsprechender Senderhythmus der Zeichen eingehalten wird. Aber wir wollten ja unbedingt lernen,
wie so was funktioniert!

Einstellmenue über Terminalprogramm

Auf dem PC muss zur Kommunikation mit dem CW-Geber ein Terminalprogramm laufen, das die
verwendete serielle Schnittstelle mit der voreingestellten Baudrate von 9.600 Baud und mit 8N1
bedient. Dazu ist jedes primitive Terminalprogramm (z.B. Hyperterminal) geeignet.

(=> Screenshot: Einstellungen im Hyperterminal)

Man muss das Programm nur davon abhalten, ein Modem am anderen Ende der seriellen Leitung zu
erwarten, weil sonst die AT-Befehle gemorst werden und keine korrekte Rückmeldung vom
"Modem" (OK) kommt. Also wird z.B. Hyperterminal in der Einstellung "Direktverbindung über
COMx" betrieben.

(=> Screenshot: Nach dem Einschalten meldet sich der 2313 und morst vor sich hin)

Damit man das Einstellmenue im 2313 herankommt, muss das Terminalprogramm beim Betätigen
der ESCAPE-Taste tatsächlich das ESC-Zeichen (hex: 1B, dezimal: 27) über die Schnittstelle senden
(das macht Hyperterminal so). Verwendet man ein Terminalprogramm, das die ESCAPE-Taste für
andere Zwecke verwendet, muss man die Software des 2313 ändern und irgend ein anderes
Kontrollzeichen auswerten.

(=> Screenshot: Der 2313 im Verstellmodus)

Hat man sich vertippt, reagiert die Eingabezeile für Morsezeichen auf die Rück- oder Backspace-
Taste, falls diese das Kontrollzeichen 8 aussendet. Die Cursortasten und andere ANSI- oder VT100-
Zeichen werden in dieser Version nicht unterstützt.

Hat man es im Terminalprogramm lieber buntig, muss man entsprechende ANSI-Code-Zeichen zu


den Menuetexten im Assemblerprogramm hinzufügen. Aber Vorsicht dabei: der ATMEL-Assembler
hat seit langem einen üblen Bug und übersetzt bestimmte Mischungen aus Byte-Konstanten und -
Texten, die in " eingeschlossen sind, nicht korrekt. Der Programmzähler kann dabei um ein oder
mehrere Worte vor- oder nachgehen, die Übersetzung richtet ein Chaos bei allen nachfolgenden
Programm-Labels an. Nach dem Ändern von .DB-Menuezeilen sollte man sich anschließend im
Listing davon überzeugen, dass die eingefügten chk-Prüfwerte adressmäßig übereinstimmen. Sonst
kommt es zu weggelassenen oder verstümmelten Zeichen oder Zeilen.

Viel Erfolg beim Experimentieren!

Betrieb der Software auf einem Board

Wer ein STK200- oder STK500-board sein Eigen nennt, kann auf den Selbstbau des 2313-
Experimentierboards auch verzichten, den Lautsprecher an das Board anschließen und die Software
auf dem Board verwenden. Dazu ist gegenüber der Eigenbau-Schaltung ein AT90S8515 auf dem
Board erforderlich, was einige Umbauten in der Software bedingt. Im Anhang können die
verschiedenen Software-Versionen heruntergeladen werden.

Beim Board STK200 ist der erforderliche Zusatzanbau eine 10-polige, zweireihige Buchse, die an
den Portausgang von Port D angeschlossen wird (ähnlich wie der Lautsprecheranschluss beim
Experimentierboard). Das NF-Ausgangsignal liegt im Gegensatz zum Experimentierboard an Bit 5
des Ports D an und wird über einen Elko von 10µF und einen Widerstand von ca. 470 Ohm an den
Lautsprecher angeschlossen. Die zweite Leitung vom Lautprecher wird auf GND der 10-poligen
Buchse gelegt. Die Software ist auf den boardeigenen Taktoszillator von 4 MHz eingestellt.

Beim STK500 muss der AT90S8515 bestückt sein. Die Anschlüsse PD0 und PD1 des 10-poligen
Postensteckers von Port D müssen an RXD bzw. TXD der RS232-SPARE-Buchse angeschlossen
werden (über mit dem Board mitgelieferte zweipolige Steckverbinder). Der Lautsprecher wird wie
beim Experimentierboard mit dem Elko und dem Widerstand beschaltet und kommt an Pin PD5 und
GND von Port D des Boards. Die Software ist auf die boardeigene Taktung mit 3,96 MHz eingestellt.
Wer per Studio-Software den Teilerfaktor anders einstellt, muss den Parameter fq in der Software
entsprechend ändern. Allerdings dürfte es bei Taktfrequenzen unterhalb von 1 MHz zu Problemen
kommen, wenn extreme NF-Frequenzen oder Gebegeschwindigkeiten eingestellt werden.

Bei der Software für beide STK Boards ist noch ein zusätzlicher Menuepunkt ansteuerbar, weil der
8515 über mehr Programmspeicher verfügt (Option x).

Beim Betrieb mit einem Board ist ferner zu berücksichtigen, dass

● die RS-232-Anschlüsse nicht über eine Beschaltung der Signale RTS und CTS verfügen, das
Hardware-Protokoll steht daher nicht zur Verfügung und muss im Terminalprogramm
abgeschaltet werden (keine Ausgabe ganzer Textdateien in einem Rutsch möglich!),
● in den RS232-Buchsen der Boards RD und TD bereits gekreuzt sind und 1 zu 1 verkabelt
werden müssen (ein Nullmodem-Kabel funktioniert hierfür nicht),
● beim STK500 beide RS232-Schnittstellen benötigt werden (zum Programmieren mittels
STUDIO und zur Kommunikation mit einem Terminalprogramm) und dass beide
unterschiedliche Baudraten verwenden (115 k bzw. 9k6).

Anhang: Software zum Download

Mit diesen Links kann die Assemblersoftware für die verschiedenen Versionen heruntergeladen
werden:
Version Hardware Chip Takt HTML-Version asm-Version
Experimentierboard AT90S2313 10 MHz Cw01.html Cw01.asm
0.1 STK200-board 4 MHz Cw01_200.html Cw01_200.asm
AT90S8515
STK500-board 3,96 MHz Cw01_500.html Cw01_500.asm

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil4/index.html1/20/2009 7:49:27 PM
http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw.gif

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw.gif1/20/2009 7:49:30 PM
CW Geber mit AT90S2313 board (C)2002 DG4FAC

18pk 18pk
Asynchrones serielles Interface 100
22µ 22µ nk XTal
100 + 10MHz
2k2 2k2 2k2 20 10 5 4
nk +
CD 16 15 6 2 RXD 2
1 PD0
DSR 6 Loop J1Normal
RD O1 12
13 I1 3
RTS 7 2 PD1
TXD
14 O2 11 Data
CTS 3 TD I2
8
DTR 8
MAX232 Loop J2Normal
O3 9
4 16 NF-Ausgang
I3 PB4
9 CTS
7 O4
DS9 5 I4 10 Control
10µ
(Stecker) RTS 14 15
PB2 PB3
1 3 4 5 470 +
+ +
22µ 22µ AT90S2313 LSP
8 Ohm
On-board-ISP Programmierinterface
18 PB6

10 9 MISO 19 PB7
SCK 17 PB5
8 7
RESET RESET
6 5 1
LED 1k
LED 1N4148
4 3
MOSI 1k
2 1
+ 47k
1µT
4 x 1N4001
Stromversorgung
~ 1
9 ... 15 V 330pK 330pK
~ 2 + 7805 +
470µ 35V 1µT

Zum PC Nullmodem-Kabel Zum Board


DSR
1 1
6 CD 6
RD RD
RTS 7 2 2 RTS
TD TD 3 7
CTS 3 CTS
8 8
4 4
9 DTR 9
DB9 5 GND
5 DB9
(Buchse) (Buchse)
http://www.avr-asm-tutorial.net/cq-dl/teil4/HYPERTE.gif

http://www.avr-asm-tutorial.net/cq-dl/teil4/HYPERTE.gif1/20/2009 7:49:33 PM
http://www.avr-asm-tutorial.net/cq-dl/teil4/CWRUN.gif

http://www.avr-asm-tutorial.net/cq-dl/teil4/CWRUN.gif1/20/2009 7:49:36 PM
http://www.avr-asm-tutorial.net/cq-dl/teil4/CWMENUE.gif

http://www.avr-asm-tutorial.net/cq-dl/teil4/CWMENUE.gif1/20/2009 7:49:38 PM
cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 4 => Cw01.asm

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Assembler-Quellcode des CW-Programmes


; **********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des 2313-Experimentier-Boards eingegeben wer- *
; * den. Ausgabe NF an PB3. Baudrate 9k6. Takt 10 MHz. *
; * AVR AT90S2313. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1 vom 28.12.2001 *
; * Bugs und Dankschreiben an info!at!avr-asm-tutorial.net *
; **********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2313def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 10000000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input
.EQU bcts = PB4 ; CTS bit Output
.EQU boc1 = PB3 ; NF-Ausgabe über OC1-Pin
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEAR,YL ; Leseadresse im EEPROM
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARL,XL ; Schreibadresse im EEPROM einstellen
; Hat nur 7 Bit, daher nur LSB
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XL,128 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = Konstante
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 10 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 10 MHz und Teiler 200: 3125
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
; rcall txreg ; Debug info
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug info
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug info
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,low(RAMEND) ; Init stack pointer im SRAM
out SPL,rmp ; nur 8-Bit-Pointer bei 2313
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pdrr,boc1 ; Ausgabe Pin OC1=PB3 auf Ausgang
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um
getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.html (1 of 2)1/20/2009 7:49:44 PM


cq-dl-Beiträge zu AVR-Mikrocontrollern

cpi rmp,chesc ; Ende-Zeichen ESCAPE?


brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück
rjmp start1 ; Ende, starte fast alles neu
getpar1:
cpi rmp,'s' ; Speichern gewählt?
breq getpars ; geh zum Speichern
cpi rmp,'l' ; Lesen gewählt?
breq getparl ; geh zum Lesen
cpi rmp,'d' ; Default-Werte gewählt?
breq getpard ; Setze Default Werte
ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
breq getpar2 ; ja, hole Zahl
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
breq getpar2 ; ja, hole Zahl
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ;
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ñ
.DB 0b01101000,5 ; $ = á, å
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.html (2 of 2)1/20/2009 7:49:44 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.asm

; ********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des 2313-Experimentier-Boards eingegeben wer- *
; * den. Ausgabe NF an PB3. Baudrate 9k6. Takt 10 MHz. *
; * AVR AT90S2313. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1 vom 28.12.2001 *
; * Bugs und Dankschreiben an info@avr-asm-tutorial.net *
; ********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2313def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 10000000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input
.EQU bcts = PB4 ; CTS bit Output
.EQU boc1 = PB3 ; NF-Ausgabe über OC1-Pin
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEAR,YL ; Leseadresse im EEPROM
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARL,XL ; Schreibadresse im EEPROM einstellen
; Hat nur 7 Bit, daher nur LSB
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XL,128 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = ccm / 200
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 10 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 10 MHz und Teiler 200: 3125
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
; rcall txreg ; Debug info
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug info
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug info
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,low(RAMEND) ; Init stack pointer im SRAM
out SPL,rmp ; nur 8-Bit-Pointer bei 2313
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pdrr,boc1 ; Ausgabe Pin OC1=PB3 auf Ausgang
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um
getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO
cpi rmp,chesc ; Ende-Zeichen ESCAPE?
brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück
rjmp start1 ; Ende, starte fast alles neu
getpar1:
cpi rmp,'s' ; Speichern gewählt?
breq getpars ; geh zum Speichern
cpi rmp,'l' ; Lesen gewählt?
breq getparl ; geh zum Lesen
cpi rmp,'d' ; Default-Werte gewählt?

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.asm (1 of 2)1/20/2009 7:49:51 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.asm

breq getpard ; Setze Default Werte


ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
breq getpar2 ; ja, hole Zahl
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
breq getpar2 ; ja, hole Zahl
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ;
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ~n
.DB 0b01101000,5 ; $ = á, °a
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01.asm (2 of 2)1/20/2009 7:49:51 PM


cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 4 => Cw01_200.asm

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Assembler-Quellcode des CW-Programmes


; **********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des STK200-Boards eingegeben werden. Die Aus- *
; * gabe der NF erfolgt an PD5. Baudrate 9k6. Takt 4 MHz. *
; * AVR AT90S8515. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1-200 vom 12.1.2002 *
; * Bugs und Dankschreiben an info!at!avr-asm-tutorial.net *
; **********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 4000000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS (nicht benutzt)
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input (beim STK nicht benutzt)
.EQU bcts = PB4 ; CTS bit Output (beim STK nicht benutzt)
.EQU pnfd = DDRD ; Port für Richtung NF-Ausgabe (8515)
.EQU doc1 = PD5 ; NF-Ausgabe über OC1B-Pin (8515)
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle 8515
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match A
reti ; Timer 1 Compare Match B
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
reti ; SPI STC, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
reti ; ANA_COMP, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEARH,YH ; Leseadresse im EEPROM
out EEARL,YL
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARH,XH ; Schreibadresse im EEPROM einstellen
out EEARL,XL
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XH,$02 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = Konstante
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 4 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
; rcall txreg ; Debug-Code!!!
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 4 MHz: 1250
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug code!!!
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug code!!!
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,HIGH(RAMEND) ; Init stack pointer im SRAM
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pnfd,doc1 ; Ausgabe Pin OC1B=PD5 auf Ausgang (8515)
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.html (1 of 2)1/20/2009 7:49:59 PM


cq-dl-Beiträge zu AVR-Mikrocontrollern

getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO
cpi rmp,chesc ; Ende-Zeichen ESCAPE?
brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück
rjmp start1 ; Ende, starte fast alles neu
getpar1:
cpi rmp,'s' ; Speichern gewählt?
brne getpar1a
rjmp getpars ; geh zum Speichern
getpar1a:
cpi rmp,'l' ; Lesen gewählt?
brne getpar1b
rjmp getparl ; geh zum Lesen
getpar1b:
cpi rmp,'d' ; Default-Werte gewählt?
brne getpar1c
rjmp getpard ; Setze Default Werte
getpar1c:
cpi rmp,'x' ; Testtext gewählt?
brne getpar1d
rjmp getparx
getpar1d:
ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
brne getpar1e
rjmp getpar2 ; ja, hole Zahl
getpar1e:
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
brne getpar1f
rjmp getpar2 ; ja, hole Zahl
getpar1f:
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ; Default-text in Speicher
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getparx: ; Test-Text ausgeben (nur in der STK-Version!)
ldi XH,HIGH(srtx) ; Zeiger X auf SRAM-Text
ldi XL,LOW(srtx)
ldi ZH,HIGH(2*tsttext) ; Zeiger Z auf Testtext
ldi ZL,LOW(2*tsttext)
getparx1:
lpm ; Lese Zeichen
st x+,R0 ; Zeichen in SRAM-Puffer
adiw ZL,1 ; nächstes Zeichen
tst R0 ; Zeichen eine Null?
brne getparx1 ; weiter mit Zeichen
rjmp getpara ; fertig
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret ; eingefügt bis hier 2313=>8515
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ñ
.DB 0b01101000,5 ; $ = á, å
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Testtext, nur in der STK-Version implementiert!
tsttext:
.DB "<THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890>",chcr,
cnul
ChkT:
.DW ChkT
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, x=Test, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,x,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.html (2 of 2)1/20/2009 7:49:59 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.asm

; ********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des STK200-Boards eingegeben werden. Die Aus- *
; * gabe der NF erfolgt an PD5. Baudrate 9k6. Takt 4 MHz.*
; * AVR AT90S8515. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1-200 vom 12.1.2002 *
; * Bugs und Dankschreiben an info@avr-asm-tutorial.net *
; ********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 4000000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS (nicht benutzt)
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input (beim STK nicht benutzt)
.EQU bcts = PB4 ; CTS bit Output (beim STK nicht benutzt)
.EQU pnfd = DDRD ; Port für Richtung NF-Ausgabe (8515)
.EQU doc1 = PD5 ; NF-Ausgabe über OC1B-Pin (8515)
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle 8515
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match A
reti ; Timer 1 Compare Match B
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
reti ; SPI STC, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
reti ; ANA_COMP, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEARH,YH ; Leseadresse im EEPROM
out EEARL,YL
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARH,XH ; Schreibadresse im EEPROM einstellen
out EEARL,XL
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XH,$02 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = ccm / 200
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 4 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
; rcall txreg ; Debug-Code!!!
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 4 MHz und Teiler 200: 1250
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug code!!!
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug code!!!
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,HIGH(RAMEND) ; Init stack pointer im SRAM
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pnfd,doc1 ; Ausgabe Pin OC1B=PD5 auf Ausgang (8515)
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um
getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO
cpi rmp,chesc ; Ende-Zeichen ESCAPE?
brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.asm (1 of 2)1/20/2009 7:50:03 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.asm

rjmp start1 ; Ende, starte fast alles neu


getpar1:
cpi rmp,'s' ; Speichern gewählt?
brne getpar1a
rjmp getpars ; geh zum Speichern
getpar1a:
cpi rmp,'l' ; Lesen gewählt?
brne getpar1b
rjmp getparl ; geh zum Lesen
getpar1b:
cpi rmp,'d' ; Default-Werte gewählt?
brne getpar1c
rjmp getpard ; Setze Default Werte
getpar1c:
cpi rmp,'x' ; Testtext gewählt?
brne getpar1d
rjmp getparx
getpar1d:
ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
brne getpar1e
rjmp getpar2 ; ja, hole Zahl
getpar1e:
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
brne getpar1f
rjmp getpar2 ; ja, hole Zahl
getpar1f:
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ; Default-text in Speicher
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getparx: ; Test-Text ausgeben (nur in der STK-Version!)
ldi XH,HIGH(srtx) ; Zeiger X auf SRAM-Text
ldi XL,LOW(srtx)
ldi ZH,HIGH(2*tsttext) ; Zeiger Z auf Testtext
ldi ZL,LOW(2*tsttext)
getparx1:
lpm ; Lese Zeichen
st x+,R0 ; Zeichen in SRAM-Puffer
adiw ZL,1 ; nächstes Zeichen
tst R0 ; Zeichen eine Null?
brne getparx1 ; weiter mit Zeichen
rjmp getpara ; fertig
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret ; eingefügt bis hier 2313=>8515
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ~n
.DB 0b01101000,5 ; $ = á, °a
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Testtext, nur in der STK-Version implementiert!
tsttext:
.DB "<THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890>",chcr,cnul
ChkT:
.DW ChkT
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, x=Test, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,x,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_200.asm (2 of 2)1/20/2009 7:50:03 PM


cq-dl-Beiträge zu AVR-Mikrocontrollern

Pfad: Home => cq-dl-Beiträge => Teil 4 => Cw01_500.asm

cq-dl-Beiträge zu ATMEL-AVR-
Mikrocontrollern

Assembler-Quellcode des CW-Programmes


; **********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des STK500-Boards eingegeben werden. Die Aus- *
; * gabe der NF erfolgt an PD5. Baudrate 9k6. 3,96 MHz *
; * AVR AT90S8515. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1-500 vom 12.1.2002 *
; * Bugs und Dankschreiben an info!at!avr-asm-tutorial.net *
; **********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 3960000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS (nicht benutzt)
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input (beim STK nicht benutzt)
.EQU bcts = PB4 ; CTS bit Output (beim STK nicht benutzt)
.EQU pnfd = DDRD ; Port für Richtung NF-Ausgabe (8515)
.EQU doc1 = PD5 ; NF-Ausgabe über OC1B-Pin (8515)
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle 8515
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match A
reti ; Timer 1 Compare Match B
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
reti ; SPI STC, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
reti ; ANA_COMP, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEARH,YH ; Leseadresse im EEPROM
out EEARL,YL
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARH,XH ; Schreibadresse im EEPROM einstellen
out EEARL,XL
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XH,$02 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = Konstante
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 4 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
; rcall txreg ; Debug-Code!!!
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 4 MHz: 1250
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug code!!!
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug code!!!
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,HIGH(RAMEND) ; Init stack pointer im SRAM
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pnfd,doc1 ; Ausgabe Pin OC1B=PD5 auf Ausgang (8515)
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.html (1 of 2)1/20/2009 7:50:11 PM


cq-dl-Beiträge zu AVR-Mikrocontrollern

getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO
cpi rmp,chesc ; Ende-Zeichen ESCAPE?
brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück
rjmp start1 ; Ende, starte fast alles neu
getpar1:
cpi rmp,'s' ; Speichern gewählt?
brne getpar1a
rjmp getpars ; geh zum Speichern
getpar1a:
cpi rmp,'l' ; Lesen gewählt?
brne getpar1b
rjmp getparl ; geh zum Lesen
getpar1b:
cpi rmp,'d' ; Default-Werte gewählt?
brne getpar1c
rjmp getpard ; Setze Default Werte
getpar1c:
cpi rmp,'x' ; Testtext gewählt?
brne getpar1d
rjmp getparx
getpar1d:
ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
brne getpar1e
rjmp getpar2 ; ja, hole Zahl
getpar1e:
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
brne getpar1f
rjmp getpar2 ; ja, hole Zahl
getpar1f:
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ; Default-text in Speicher
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getparx: ; Test-Text ausgeben (nur in der STK-Version!)
ldi XH,HIGH(srtx) ; Zeiger X auf SRAM-Text
ldi XL,LOW(srtx)
ldi ZH,HIGH(2*tsttext) ; Zeiger Z auf Testtext
ldi ZL,LOW(2*tsttext)
getparx1:
lpm ; Lese Zeichen
st x+,R0 ; Zeichen in SRAM-Puffer
adiw ZL,1 ; nächstes Zeichen
tst R0 ; Zeichen eine Null?
brne getparx1 ; weiter mit Zeichen
rjmp getpara ; fertig
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret ; eingefügt bis hier 2313=>8515
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ñ
.DB 0b01101000,5 ; $ = á, å
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Testtext, nur in der STK-Version implementiert!
tsttext:
.DB "<THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890>",chcr,
cnul
ChkT:
.DW ChkT
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, x=Test, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,x,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

©2002 by Gerhard Schmidt, DG4FAC


Webseite mit den Beiträgen: http://www.avr-asm-tutorial.net/cq-dl/index.html
Benutzung, Kopie und Weiterverbreitung der Seiten zulässig, solange die Copyright-Angaben im Text bleiben.

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.html (2 of 2)1/20/2009 7:50:11 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.asm

; ********************************************************
; * CW.asm gibt Morsezeichen aus, die im EEPROM-Speicher *
; * gespeichert sind und die über die serielle Schnitt- *
; * stelle des STK500-Boards eingegeben werden. Die Aus- *
; * gabe der NF erfolgt an PD5. Baudrate 9k6. 3,96 MHz *
; * AVR AT90S8515. Programm (C)2002 by DG4FAC G.Schmidt *
; * Version 0.1-200 vom 12.1.2002 *
; * Bugs und Dankschreiben an info@avr-asm-tutorial.net *
; ********************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Benutzte Register
;
; Register R0 wird für Lesen im Programmspeicher benutzt
; Register R0..R9 werden für Berechnungen benutzt
;
.DEF rcml = R10 ; Compare Match-Zahl, LSB
.DEF rcmh = R11 ; dto., MSB
.DEF rikl = R12 ; Interrupt-Anzahl kurz, LSB
.DEF rikh = R13 ; dto., MSB
.DEF rill = R14 ; Interrupt-Anzahl lang, LSB
.DEF rilh = R15 ; dto., MSB
.DEF rmp = R16 ; Multipurpose register, nicht bei Ints
.DEF rim = R17 ; Interrupt multi-purpose
.DEF rfl = R18 ; Flag Register, bei Ints und Normal
.DEF rst = R19 ; Statusregister bei Interrupts
.DEF rnsc = R20 ; Anzahl Punkte/Striche beim Senden
.DEF rmcd = R21 ; Morsecode beim Senden
.DEF x22 = R22 ; unbenutzt
.DEF x23 = R23 ; unbenutzt
.DEF rctl = R24 ; Zähler für Interrupt Tonerzeugung
.DEF rcth = R25 ; (wird als Doppelregister verwendet)
;
; Register XH:XL R27:R26 Zeiger in den Empfangspuffer
; Register YH:YL R29:R28 Zeiger beim Senden
; Register ZH:ZL R31:R30 Zeiger für Lesen im Programmspeicher
;
; Bits im Flagregister
;
.EQU besc = 7 ; ESCape-Sequenz, hole Parameter
.EQU bmesc = 0x80 ; Maskenbyte für ESC
.EQU bstx = 6 ; Starte Sendeprozess
.EQU bmstx = 0x40 ; Maskenbyte für bstx
.EQU bctx = 5 ; Beende Sendeprozess nach Leerzeichen
.EQU bmctx = 0x20 ; Maskenbyte für bctx
.EQU btxa = 4 ; Sendeprozess aktiv
.EQU bmtxa = 0x10 ; Maskenbyte für btxc
.EQU btxe = 3 ; Abschluss des Sendens
.EQU bmtxe = 0x08 ; Maskenbyte für btxe
.EQU bpl = 2 ; Lange Pause zur Buchstabentrennung
.EQU bmpl = 0x04 ; Maskenbyte für bpl
.EQU bpk = 1 ; Kurze Pause zur Punkt/Strich-Trennung
.EQU bmpk = 0x02 ; Maskenbyte für bpk
.EQU bquiet = 0 ; Dauerhaft inaktiviert bei Leerzeichen
.EQU bmquiet = 0x01 ; Maskenbyte für bquiet
;
; Default-Werte
;
.EQU cfrq=1000 ; NF-Frequenz
.EQU cbpm=60 ; Gebegeschwindigkeit
;
; Basisdefinitionen variabel nach Schaltung
;
.EQU fqu = 3960000 ; Quarzfrequenz des AVR
.EQU fbd = 9600 ; Baudrate des UART
.EQU pctrl = PORTB ; Control-Port für RTS/CTS (nicht benutzt)
.EQU pdrr = DDRB ; Datenrichtungsregister Controlport
.EQU brts = PB2 ; RTS bit Input (beim STK nicht benutzt)
.EQU bcts = PB4 ; CTS bit Output (beim STK nicht benutzt)
.EQU pnfd = DDRD ; Port für Richtung NF-Ausgabe (8515)
.EQU doc1 = PD5 ; NF-Ausgabe über OC1B-Pin (8515)
;
; Umrechnungen in Timer- und Counterwerte
;
.EQU nps = 8 ; Prescaler-Einstellung von Timer 1
.EQU ccm = fqu/nps/2; Konstante für Compare Match
.EQU cint =2941 ; Konstante für Int-Berechnung,
; experimentell ermittelt
;
; Definitionen fix
;
.EQU bddv = (fqu/(16*fbd))-1 ; Baudraten-Teiler
.EQU cnul = 0x00 ; Ende für nullterminierte Strings
.EQU chbsp = 0x08 ; Backspace character
.EQU chcr = 0x0D ; Carriage Return character
.EQU chlf = 0x0A ; Line Feed character
.EQU chff = 0x0C ; Form Feed character
.EQU chesc= 0x1B ; ESCape-Zeichen
;
; Definitionen I/O
;
; Definitionen für Timer-Controlregister TCCR1A
.EQU t1aus = 0b10000000 ; Schaltet den NF-Ausgang aus
.EQU t1ein = 0b01000000 ; Schaltet den NF-Ausgang ein
; Definition für Timer-Interrupt-Mask-Register TIMSK
.EQU t1CompInt=0b01000000 ; Interrupt bei Compare Match
; Definition für Timer-Controlregister TCCR1B
.EQU t1TaktInt=0b00001010 ; Timer-Takt CLK / 8, Clear Comp
; Definitionen für UART-Betrieb in UCR
.EQU siorxtx = 0b00011000 ; Betrieb RX und TX ohne Int
.EQU siorxint= 0b10011000 ; Betrieb RX mit Int, TX ohne Int
; Definition für den SLEEP-Mode in MCUCR
.EQU sleepmode=0b00100000 ; Aufwachen bei Interrupt
;
; Positionen im SRAM
;
.EQU sfrq = 0x0060 ; Eingestellte NF-Frequenz, Wort
.EQU sbpm = 0x0062 ; Eingestellte Geschwindigkeit, Byte
.EQU srtx = 0x0063 ; RAM-Puffer für Ein-/Ausgabezeile
.EQU srte = 0x00B3 ; Ende des nutzbaren Puffers, benutzt werden
; auch zwei weitere Folgebytes
;
; Programm beginnt hier
;
.CSEG
.ORG 0x0000
;
; Reset- und Interrupt-Sprungtabelle 8515
;
rjmp start ; Reset-Vector
reti ; Ext Int 0, nicht benutzt
reti ; Ext Int 1, nicht benutzt
reti ; Timer 1 Capture Event, nicht benutzt
rjmp itc1m ; Timer 1 Compare Match A
reti ; Timer 1 Compare Match B
reti ; Timer 1 Overflow, nicht benutzt
reti ; Timer 0 Overflow, nicht benutzt
reti ; SPI STC, nicht benutzt
rjmp iurxc ; UART Rx Complete
reti ; UART Tx data register empty, nicht benutzt
reti ; UART Tx All sent, nicht benutzt
reti ; ANA_COMP, nicht benutzt
;
; Interrupt-Service-Routinen
;
itc1m: ; Timer 1 Compare Match Interrupt
in rst,SREG ; Rette Statusregister
sbiw rctl,1 ; Zähler eins abzählen
brne itc1mz ; Raus, wenn nicht Null
mov rcth,rikh ; Setze Zähler auf kurze Dauer
mov rctl,rikl
ldi rim,t1aus ; Ton auf aus
tst rnsc ; Zeichen fertig gesendet?
breq itc1m0 ; Verzweige, wenn Zeichen fertig
sbrc rfl,bpk ; kurze Pausen-Flag?
rjmp itc1ms ; Pause zwischen Punkt/Strich war schon
sbr rfl,bmpk ; Setze kurze Pause-Flag
rjmp itc1my ; und Ausgabe auf inaktiv, fertig
itc1ms: ; Sende nächsten Punkt/Strich
cbr rfl,bmpk ; Lösche kurze Pause-Flag
ldi rim,t1ein; Ton an = Toggle
dec rnsc ; Weiteren Punkt/Strich gesendet
rol rmcd ; Punkt oder Strich senden?
brcc itc1my ; Punkt senden
mov rcth,rilh ; Lange Dauer einstellen
mov rctl,rill
rjmp itc1my
itc1m0: ; Zeichen fertig gesendet
sbrc rfl,bctx ; Sendung beenden?
rjmp itc1mx
sbrc rfl,bpl ; Lange Pause senden?
rjmp itc1mn ; Nächsten Buchstaben beginnen
sbr rfl,bmpl ; Setze langes Pausen-Flag
mov rcth,rilh ; Dauer auf lang stellen
mov rctl,rill
itc1my: ; Stelle Modus inaktiv/toggle ein
sbrc rfl,bquiet ; bei Leerzeichen Ton aus
ldi rim,t1aus ; Ton auf aus
out TCCR1A,rim
itc1mz:
out SREG,rst ; Stelle Status wieder her
reti
itc1mn:
cbr rfl,bmpl ; Langes Pausen-Flag aus
ld rim,y+ ; Nächsten Buchstaben lesen
tst rim ; Null-Terminator
breq itc1mn1
cpi rim,chcr ; Ende der Zeile?
brne itc1mn2
itc1mn1:
sbr rfl,bmctx ; Setze beenden-Flag
ldi rim,' ' ; Sende noch ein Leerzeichen
itc1mn2:
out UDR,rim ; Debug
subi rim,0x20 ; ASCII-Control-Zeichen weg
brcc itc1mn3
ldi rim,'?'-0x20 ; Sende Fragezeichen
itc1mn3:
cpi rim,0x40 ; Kleinbuchstabe?
brcs itc1mn4
subi rim,0x20 ; in Grossbuchstaben wandeln
cpi rim,0x40
brcs itc1mn4
ldi rim,'?'-0x20
itc1mn4:
add rim,rim ; Mal 2 für Tabelle
push ZH ; Register retten
push ZL
push R0
ldi ZH,HIGH(2*morse) ; Zeichentabelle laden
ldi ZL,LOW(2*morse)
add ZL,rim ; Zeichen dazu zählen
brcc itc1mn5 ; Kein Übertrag?
inc ZH ; Übertrag
itc1mn5:
lpm ; Lese Zeichencode aus Tabelle
mov rmcd,R0 ; in Zeichencode-Register
adiw ZL,1 ; Zeiger auf nächstes Byte
lpm ; aus Tabelle lesen
mov rnsc,R0 ; Anzahl Striche/Punkte
pop R0 ; Wieder herstellen der Register
pop ZL
pop ZH
tst rnsc ; Undefiniertes Zeichen?
breq itc1mn ; Überspringe Zeichen
sbr rfl,bmquiet ; Leerzeichen
sbrs rnsc,7 ; Leerzeichen?
cbr rfl,bmquiet ; Kein Leerzeichen
cbr rnsc,0x80 ; Lösche höchstes Bit
mov rim,YL ; CTS einschalten?
sub rim,XL
brcs itc1mn6 ; Ausschalten
cpi rim,3
brcs itc1mn6
cbi pctrl,bcts ; CTS einschalten
rjmp itc1ms
itc1mn6:
sbi pctrl,bcts ; CTS ausschalten
rjmp itc1ms ; Sende ein Zeichen
itc1mx: ; Sendung einstellen
clr rim ; Timer 1 abschalten
out TCCR1B,rim ; Timer-Takt aus
out TCNT1H,rim ; Timer auf Null stellen
out TCNT1L,rim
out TIMSK,rim ; Timer Interrupts aus
out TCCR1A,rim ; Timer Compare Mode aus
cbr rfl,bmctx+bmtxa ; Ende-Flag und aktiv ausschalten
sbr rfl,bmtxe ; Beenden-Flag einschalten
ldi YH,HIGH(srte) ; Buffer auf Ende
ldi YL,LOW(srte)
st Y,rim ; Null-terminieren
rjmp itc1mz
;
; UART Rx Complete Interrupt
;
iurxc:
in rst,SREG ; Rette Statusregister
in rim,UDR ; Lese Zeichen von SIO
cpi rim,chesc ; ESCape-Sequenz?
brne iurx1
sbr rfl,bmesc ; Setze ESCape-Bit
rjmp iurxz
iurx1:
cpi rim,chbsp ; Backspace-Char?
brne iurx2
cpi XL,LOW(srtx) ; Schon auf Anfang?
breq iurxz
sbiw XL,1 ; Eine Position zurück
ldi rim,chcr ; Zeilenabschluss
st x+,rim
clr rim ; Null-terminieren
st x,rim
sbiw XL,1 ; zurück
ldi rim,chbsp ; Backspace zurücksenden
rjmp iurxe ; Echo character
iurx2:
cpi XL,low(srte) ; Pufferüberlauf?
brcs iurx3 ; Nein, weiter
ldi rim,chcr ; Character überschreiben
iurx3:
cpi rim,chcr ; Zeilenende?
brne iurxw ; Nein, in Puffer und fertig
sbrs rfl,btxa ; Überspringe Ausgabe wenn aktiv
out UDR,rim ; Carriage Return schon mal ausgeben
st x+,rim ; CR-Zeichen anhängen
clr rim ; Null terminieren
st x,rim
ldi XH,HIGH(srtx) ; Puffer auf Anfang
ldi XL,LOW(srtx)
sbr rfl,bmstx ; Über Flag Sender starten
ldi rim,chlf ; Sende Zeilenvorschub
rjmp iurxe ; Echo Line-Feed
iurxw:
st x+,rim ; Speichere character
ldi rim,chcr ; Abschluss terminieren
st x+,rim ; mit Carriage return
clr rim ; Null-terminieren
st x,rim
sbrs rfl,btxa ; Sender aktiv?
rjmp iurxs ; Nein, CTS nicht prüfen
mov rim,YL ; CTS ein oder aus?
sub rim,XL ; Distanz zwischen Ein- und Ausgabe
brcs iurxo ; Eingabe > Ausgabe: CTS aus
cpi rim,3 ; mindestens zwei Zeichen Vorlauf?
brcs iurxo ; Nein, dann CTS ausschalten
cbi pctrl,bcts ; CTS einschalten
rjmp iurxs ; Zeichen herstellen und raus
iurxo:
sbi pctrl,bcts ; CTS ausschalten
iurxs:
sbiw XL,2 ; Char wieder herstellen
ld rim,x+ ; durch Lesen im SRAM
iurxe:
sbrs rfl,btxa ; Keine Ausgabe, wenn aktiv
out UDR,rim ; Echo character an SIO zurück
iurxz:
out SREG,rst ; Stelle Status wieder her
reti ; Ende des Interrupts
;
; Diverse eigenständige Unterprogramme
;
; Kopiert den EEPROM-Inhalt in das SRAM
;
ecopy:
sbic EECR,EEWE ; Warte, bis EEPROM bereit
rjmp ecopy ; Noch nicht bereit
clr YH ; Startadresse im EEPROM auf Null
clr YL
ldi ZH,HIGH(sfrq) ; Startadresse im SRAM
ldi ZL,LOW(sfrq) ; auf ersten Parameter
ecopy1:
out EEARH,YH ; Leseadresse im EEPROM
out EEARL,YL
; 2313 hat nur 128 Bytes, daher nur unteres Register
sbi EECR,EERE ; Lese-Strobe setzen
cbi EECR,EERE ; und wieder ausschalten
in rmp,EEDR ; Byte aus EEPROM-Datenregister lesen
st Z+,rmp ; und in SRAM schreiben
adiw YL,1 ; nächste EEPROM-Adresse anwählen
tst rmp ; Null-Terminator?
brne ecopy1 ; Nein: weiter kopieren
ret
;
; Schreibe Parameter in das EEPROM zurück
;
ewrite:
ldi ZH,HIGH(sfrq) ; Zeiger auf SRAM
ldi ZL,LOW(sfrq)
clr XH ; Zeiger in das EEPROM
clr XL
ewrite1:
sbic EECR,EEWE ; Frage Write-Bit im EEPROM
rjmp ewrite1 ; ab und wiederhole bis EEPROM ready
out EEARH,XH ; Schreibadresse im EEPROM einstellen
out EEARL,XL
ld rmp,Z+ ; Lese Byte aus SRAM in Register
out EEDR,rmp ; in das EEPROM-Datenregister
cli ; Keine Interrupts mehr beim Schreibvorgang
sbi EECR,EEMWE ; Setze EEPROM Master Write Enable
sbi EECR,EEWE ; Löse Schreibvorgang im EEPROM aus
sei ; Jetzt Interrupts wieder zulassen
adiw XL,1 ; Nächste EEPROM-Adresse in X-Zeiger
cpi XH,$02 ; Ende EEPROM erreicht?
brcc ewrite2 ; Überlänge! Null fehlt! Abbrechen!
tst rmp ; Nullterminiert?
brne ewrite1 ; Noch weitere Bytes schreiben
ewrite2:
ret
;
; Lese16 wandelt eine ASCII-Zahl im Puffer in binär
; in R1:R0, bei Fehler Rückkehr mit gesetztem Carry-Bit
;
lese16:
clr R0 ; Leeren Resultat-Register R1:R0
clr R1
ldi ZH,HIGH(srtx) ; Zeige auf Pufferanfang
ldi ZL,LOW(srtx)
lese16a:
ld rmp,Z+ ; Lese ASCII-Ziffer aus SRAM
cpi rmp,chcr ; Ende der Zahl mit Carriage Return?
breq lese16ok ; Zahl mit Carriage Return beendet
cpi rmp,cnul ; Ende der Zahl mit Nullterminiert?
breq lese16ok ; Ende mit Nullterminierung
cpi rmp,'9'+1 ; Ziffer > ASCII-9?
brcc lese16no ; Ja, Fehler!
cpi rmp,'0' ; Ziffer < ASCII-0
brcs lese16no ; Ja, auch Fehler
subi rmp,'0' ; Wandle Ziffer in binär
; Ab hier wird das bisherige Resultat mit 10 multi-
; pliziert
mov R2,R0 ; Kopiere Binärzahl in Hilfsregister R3:R2
mov R3,R1
add R0,R0 ; Multipliziere mit 2 durch Addieren 16 Bit
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R2 ; Addiere die Kopie der Zahl
adc R1,R3
brcs lese16no ; Überlauf beim Addieren, Fehler!
add R0,R0 ; Multipliziere mit 2 durch Addieren
adc R1,R1
brcs lese16no ; Überlauf beim Addieren, Fehler!
; Hier ist das Multiplizieren mit 10 beendet.
add R0,rmp ; Addiere Ziffer zum Resultat hinzu
brcc lese16a ; Kein Überlauf des unteren Bytes
inc R1 ; Überlauf, oberes Byte erhöhen
brne lese16a ; Kein Überlauf des oberen Bytes
lese16no:
sec ; Setze Carry-Bit bei Fehler und kehre zurück
ret
lese16ok:
clc ; Clear Carry bei fehlerfrei
ret
;
; Wandle 16-Bit-Zahl in R1:R0 in ASCII in R4..R9 (nullterm.)
; unterdrücke führende Nullen, sende Ergebnis ohne führende
; Nullen über die SIO
;
b16asc:
clr ZH ; Z zeigt auf höchste ASCII-Ziffer in
ldi ZL,4 ; Register R4 (Zeiger in Register!)
ldi rmp,HIGH(10000) ; Beginne mit Zehntausendern
mov R3,rmp ; oberes Byte in R3
ldi rmp,LOW(10000)
mov R2,rmp ; unteres Byte in R2
rcall b16sub ; Ermittle ASCII-code der Zehntausender
; Stelle durch fortgesetztes Subtrahieren von 10000
ldi rmp,HIGH(1000) ; Weiter mit Tausendern
mov R3,rmp
ldi rmp,LOW(1000)
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Tausender
clr R3 ; Weiter mit Hunderten
ldi rmp,100
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Hunderter
ldi rmp,10 ; Weiter mit Zehnern
mov R2,rmp
rcall b16sub ; Ermittle ASCII-Code der Zehner
ldi rmp,'0' ; Rest sind Einer
add rmp,R0
mov R8,rmp ; R8 kriegt die ASCII-Einer
clr R9 ; Nullterminieren in R9
ldi ZL,4 ; Z auf 10000-er Zeichen
b16asc1:
cpi ZL,9 ; Ende der Zeichenkette erreicht?
breq b16asc2 ; Ja, raus
ld rmp,z+ ; Zeichen aus Register kopieren
cpi rmp,'0' ; Führende Null?
breq b16asc1 ; Ja, weitermachen
b16asc2:
dec ZL ; auf vorheriges Zeichen setzen
;
; Sende nullterminierten Text aus SRAM an SIO
; Z zeigt nicht ins SRAM, sondern in die Register mit
; dem Ergebnis!
; Das Registerpaar Z zeigt auf das erste Zeichen
;
txstxt:
ld rmp,z+ ; Lese Zeichen aus SRAM/Register
tst rmp ; Nullterminator erreicht?
breq txstxt1 ; Ja, raus und fertig
rcall txch ; Sende character über SIO
rjmp txstxt ; Weitermachen mit nächstem Zeichen
txstxt1:
ret
;
; Ermittle ASCII-Code einer Ziffer der 16-Bit-Binärzahl in
; R1:R0 durch fortgesetztes Subtrahieren einer 16-Bit-
; Hilfszahl (10000, 1000, 100, 10) in R3:R2. Tritt ein
; Überlauf ab, dann ist die Ziffer gefunden
; (Unterroutine für b16asc)
;
b16sub:
ldi rmp,'0' ; Setze ASCII-Null
b16sub1:
sub R0,R2 ; Subtrahiere die Hilfszahl
sbc R1,R3 ; in 16-bit
brcs b16sub2 ; Ende subtrahieren erreicht?
inc rmp ; Einer geht noch!
rjmp b16sub1 ; Weiter mit subtrahieren!
b16sub2:
add R0,R2 ; Zu weit, addiere wieder zurück
adc R1,R3
st Z+,rmp ; ASCII-Ziffer in Register schreiben
ret ; und zurück
;
; Sende nullterminierten Text aus dem Programmspeicher
; über die SIO aus
;
txtext:
lpm ; Lese Zeichen aus Programmspeicher mit Zeiger Z
tst R0 ; Ergebnis im Register R0 hat Null erreicht?
breq txtend ; Ja, raus aus der Routine
mov rmp,R0 ; Kopiere Zeichen in Senderegister
rcall txch ; Sende character mit Prüfung
adiw zl,1 ; Zeiger auf nächstes Zeichen
rjmp txtext ; Weitermachen bis Null
txtend:
ret ; Kehre zurück
;
; Liste alle Parameter über die SIO-Schnittstelle auf
;
txpar:
ldi ZH,HIGH(2*txtpar1) ; Sende Parametervorspann
ldi ZL,LOW(2*txtpar1) ; für NF-Frequenz
rcall txtext
lds R0,sfrq ; Zeige eingestellte Frequenz an
lds R1,sfrq+1
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar2) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar2) ; Geschwindigkeit an
rcall txtext
lds R0,sbpm ; Zeige Geschwindigkeit an
clr R1 ; nur 8 Bit!
rcall b16asc ; Wandle in ASCII und sende Zahl
ldi ZH,HIGH(2*txtpar3) ; Zeige Vorspann für Counter-
ldi ZL,LOW(2*txtpar3) ; Compare-Match-Zahl ccm an
rcall txtext
mov R1,rcmh ; Compare-Match-Zahl in R1:R0
mov R0,rcml
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar4) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar4) ; Anzahl NF-Ints bei Punkt an
rcall txtext
mov R1,rikh ; Anzahl Ints bei Punkt in R1:R0
mov R0,rikl
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar5) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar5) ; Anzahl NF-Ints bei Strich an
rcall txtext
mov R1,rilh ; Anzahl Ints bei Strich in R1:R0
mov R0,rill
rcall b16asc ; Wandle in ASCII und sende
ldi ZH,HIGH(2*txtpar6) ; Zeige Vorspann für
ldi ZL,LOW(2*txtpar6) ; Ausgabetext an
rcall txtext
ldi ZH,HIGH(srtx) ; Zeiger Z auf Ausgabetext im SRAM
ldi ZL,LOW(srtx)
rjmp txstxt ; Sende Inhalt SRAM nullterminiert
;
; 32-Bit durch 16-Bit-Division
;
; Dividiert 32-Bit-Zahl in R3:R2:R1:R0 durch R5:R4
; Ergebnis in R7:R6 (Ergebnis darf nicht > 16 Bit sein!)
;
div32:
clr R7 ; Clear Ergebnis-Register R7:R6
clr R6
inc R6 ; Stopbit setzen für 16 Divisionsschritte
div32a:
clc ; Null in Carry schieben
rol R0 ; Multipliziere Divident mit 2
rol R1
rol R2
rol R3
brcs div32e ; Carry ist herausgerollt? Dann 1!
cp R3,R5 ; Vergleiche oberes Byte
brcs div32n ; Ergebnis ist kleiner, also eine 0
brne div32e ; Ergebnis ist größer, also eine 1
cp R2,R4 ; Vergleich MSB gleich, vergleiche unteres
; Byte
brcs div32n ; Unteres Byte kleiner, also eine 0
div32e:
sub R2,R4 ; Ziehe den Divisor von den oberen 16 Bit ab
sbc R3,R5
sec ; Setze das Carry-Bit, Ergebnis ist eine 1
rjmp div32s ; Zum Reinschieben in das Ergebnis
div32n:
clc ; Lösche Carry-Bit, Ergebnis ist eine 0
div32s:
rol R6 ; Schiebe Carry-Bit von rechts in Ergebnis
rol R7
brcc div32a ; Ende, wenn eine 1 links herausrollt
ret
;
; Multipliziert 16-Bit-Zahl in R1:R0 mit 16-Bit-Zahl in R5:R4
; Ergebnis 32 Bit in R9:R8:R7:R6, für jeden Zahlenbereich
;
Mul16:
clr R3 ; Leere obere zwei Bytes der 16-Bit-Zahl
clr R2
clr R9 ; Leere Ergebnis-Register R9:R8:R7:R6
clr R8
clr R7
clr R6
Mul16a:
clc ; Null ins Carry-Bit
ror R5 ; Schiebe unterstes Bit Divisor in Carry
ror R4 ; und dividiere Multiplikant durch 2
brcc Mul16b ; Bit war eine 0, Addition überspringen
add R6,R0 ; addiere Multiplikator 32 Bit zum
adc R7,R1 ; bisherigen Ergebnis, jeweils mit
adc R8,R2 ; Überlauf
adc R9,R3
Mul16b:
tst R4 ; Schon alle Bits ausmultipliziert?
brne Mul16c ; Nein, LSB nicht Null, weiter
tst R5 ; Teste auch oberes Byte
brne Mul16c ; Nein, MSB nicht Null, weiter
ret ; Fertig
Mul16c:
clc ; Null in Carry-Bit schieben
rol R0 ; Zahl durch Linksschieben mit 2
rol R1 ; multiplizieren
rol R2
rol R3
rjmp Mul16a ; und weiter dividieren
;
; Dividiert 32 Bit-Zahl in R3:R2:R1:R0 durch eine
; 8-Bit-Zahl in R4 und durch 256, Ergebnis gerundet
; in R8:R7, Wertebereich beachten!
;
Div32_8:
clr R8 ; Ergebnisspeicher R8:R7:R6 leeren
clr R7
clr R6
inc R6 ; Stopbit nach 24 Schritten setzen
Div32_8a:
clc ; Carry-Bit leeren
rol R0 ; Divident mit 2 multiplizieren
rol R1 ; durch Linksschieben
rol R2
rol R3
brcs Div32_8e ; 1 herausgerollt, Ergebnis=1
cp R3,R4 ; Vergleiche oberstes Byte mit Divisor
brcs Div32_8n ; Kleiner, Ergebnis = 0
Div32_8e:
sub R3,R4 ; Ziehe Divisor von oberstem Byte ab
sec ; Setze Carry für Ergebnis = 1
rjmp Div32_8b ; Ins Ergebnis schieben
Div32_8n:
clc ; Clear Carry für Ergebnis = 0
Div32_8b:
rol R6 ; Ergebnis-Bit von rechts her hineinrotieren
rol R7
rol R8
brcc Div32_8a ; Weiter, wenn eine Null herausrollt
rol R6 ; Binäre Kommastelle eine 1, aufrunden?
brcc Div32_8z ; Nein, wenn Null
inc R7 ; Aufrunden LSB Ergebnis
brne Div32_8z ; Kein Überlauf bei LSB-Erhöhung
inc R8 ; Aufrunden MSB
Div32_8z:
ret
;
; Rechne Parameter um in Timer- und Zählerwerte
; Oben definiert: ccm = Taktfrequenz / Prescale 8 / 2
; cint = ccm / 200
; Compare-Match-Zahl für Timer 1 = ccm / NF-Frequenz
; Anzahl Ints bei Punkt = cint * NF-Frequenz / Speed /256
; Anzahl Ints bei Punkt = Anzahl Ints bei Strich * 3
;
calctc:
ldi rmp,BYTE4(ccm) ; Taktabhängige Konstante ccm
mov R3,rmp ; in R3:R2:R1:R0, bei 4 MHz: 625.000
ldi rmp,BYTE3(ccm) ; oder 0x00098968
mov R2,rmp
ldi rmp,BYTE2(ccm)
mov R1,rmp
ldi rmp,BYTE1(ccm)
mov R0,rmp
lds R4,sfrq ; durch NF-Frequenz in R5:R4
lds R5,sfrq+1
rcall div32 ; ergibt Compare Match-Zahl 16-Bit
; rcall txreg ; Debug-Code!!!
mov rcmh,R7 ; Ergebnis in Speicher rcmh:rcml
mov rcml,R6
ldi rmp,HIGH(cint) ; Konstante für Anzahl Ints
mov R1,rmp ; bei 4 MHz und Teiler 200: 1250
ldi rmp,LOW(cint)
mov R0,rmp
lds R4,sfrq ; Mal NF-Frequenz in Hz
lds R5,sfrq+1
rcall mul16 ; Multplizieren 16 Bit * 16 Bit
; rcall txreg ; Debug code!!!
mov R3,R9 ; Ergebnis in R9..R6 nach R3..R0 kopieren
mov R2,R8
mov R1,R7
mov R0,R6
lds R4,sbpm ; durch Gebegeschwindigkeit teilen
rcall div32_8 ; teilen 32-Bit durch 8-Bit
; rcall txreg ; Debug code!!!
mov rikh,R8 ; in Kurzspeicher kopieren
mov rikl,R7
mov rilh,R8 ; und in Langspeicher kopieren
mov rill,R7
add rill,rill ; Langspeicher mit 2 malnehmen
adc rilh,rilh ; durch Addieren
add rill,rikl ; und noch einmal dazu zählen
adc rilh,rikh ; macht 3 mal so lang
ret
;
; Debug code
;
; Display Byte in rmp in Hex an die SIO
;
;txbhx:
; push rmp
; swap rmp
; rcall txnhx1
; pop rmp
;txnhx1:
; cbr rmp,0b11110000
; subi rmp,-'0'
; cpi rmp,'9'+1
; brcs txnhx2
; subi rmp,-7
;txnhx2:
; rcall txch
; ret
;
; Display Register R0..R9 in Hex an SIO
;
;txreg:
; ldi rmp,chcr
; rcall txch
; clr ZH
; clr ZL
;txreg1:
; ld rmp,Z+
; rcall txbhx
; ldi rmp,' '
; rcall txch
; cpi ZL,11
; brcs txreg1
; ldi rmp,chcr
; rcall txch
; ret
;
; Hauptprogramm-Loop, Restart-Vektor
;
start:
ldi rmp,HIGH(RAMEND) ; Init stack pointer im SRAM
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,bddv ; Baudrate des UART einstellen
out UBRR,rmp
ldi rmp,siorxtx ; UART Tx und Rx ein, Ints aus
out UCR,rmp
cbi pdrr,brts ; Bit Richtung ist RTS-Eingang
sbi pdrr,bcts ; Bit Richtung ist CTS-Ausgang
sbi pctrl,bcts ; CTS ausschalten (invertiert!)
rcall ecopy ; Kopiere EEPROM-Inhalt nach RAM
ldi ZH,high(2*txtid) ; Sende ID-Text an SIO
ldi ZL,low (2*txtid)
rcall txtext
clr rfl ; Flag auf Anfangswert leer
;
; Bedingungen für Interrupt-Betrieb herstellen
;
start1:
rcall calctc ; Rechne Timerwerte und Ints aus
rcall txpar ; Gib die eingestellten Werte über SIO
ldi ZH,HIGH(2*txtcur) ; Sende Cursor-String
ldi ZL,LOW(2*txtcur)
rcall txtext
ldi rmp,sleepmode ; Mode Idle für Sleep einstellen
out MCUCR,rmp ; Aufwachen durch Interrupts
ldi rmp,siorxint ; Enable RX mit Interrupt
out UCR,rmp
cbi pctrl,bcts ; Aktiviere CTS-Leitung
sei ; Enable General Interrupt Flag
ldi XH,HIGH(srtx) ; Puffer auf Anfang stellen
ldi XL,LOW(srtx)
rcall starttx ; und Text in CW aussenden
ldi YH,HIGH(srte+3) ; Ausgabepointer hinter Ende
ldi YL,LOW(srte+3) ; des Puffers stellen
ldi XH,high(srtx+1) ; Puffer wieder auf Anfang
ldi XL,low(srtx+1) ; und überschreiben des Textes
clr rmp ; Null-Terminierung schreiben
st -x,rmp
ldi rmp,chcr ; Setze leeres Textfeld mit CR
st -x,rmp ; Jetzt zeigt X-Zeiger auf Anfang
;
; Interrupt loop, ab jetzt praktisch nur Kreisverkehr
; mit Ausbruch bei gesetzten Flagbits
;
loop:
sleep ; CPU schlafen schicken
nop ; Dummy-Befehl, bleibt bei Schlaf hier stehen
nop ; nach dem Aufwachen ausgeführt
sbrc rfl,bstx ; Sendeflag von Int-Routine gesetzt?
rjmp starttx ; Ja: Starte Sendevorgang
sbrc rfl,btxe ; Senden-beenden von Int-Routine?
rjmp stoptx ; Beende Sendevorgang
sbrc rfl,btxa ; Ist die Sendeausgabe aktiv?
rjmp loop ; (Während Aussendung keine Parameter!)
sbrc rfl,besc ; Parameter mit Menue holen?
rjmp getpar ; Hole Parameter über SIO
rjmp loop ; weiter im Kreis herum
;
; Startet Sendeprozess
;
starttx:
sbrc rfl,btxa ; Nicht neu starten, wenn schon aktiv
rjmp loop ; Wieder raus!
cbr rfl,bmstx ; Setze Flag bit zurück
sbi pctrl,bcts ; Stop CTS-Leitung
ldi YH,HIGH(srtx) ; Sende-Pointer auf Pufferanfang
ldi YL,LOW(srtx)
mov rcth,rikh ; Kurze Verzögerung bis zum Start
mov rctl,rikl
clr rnsc ; Auszugebendes Zeichen beendet, provoziert
; Laden des nächsten Zeichens bei der Senderoutine
sbi pnfd,doc1 ; Ausgabe Pin OC1B=PD5 auf Ausgang (8515)
clr rmp ; Setze Timer-Werte
out TCCR1A,rmp ; OC1 inaktivieren
out TCNT1H,rmp ; Timer-Register auf Null setzen
out TCNT1L,rmp
out OCR1AH,rcmh ; Compare Match auf Dauer ent-
out OCR1AL,rcml ; sprechend der NF-Frequenz
ldi rmp,t1CompInt ; Ermögliche Compare Int
out TIMSK,rmp
ldi rmp,t1TaktInt ; Clear Timer on Compare
; Match und Prescaler CK/8
out TCCR1B,rmp ; Timer-Takt starten
rjmp loop ; und CPU bis zum Timer-Int schlafen legen
; ab jetzt läuft wieder alles automatisch ab
;
; Beendet Sendevorgang
;
stoptx:
cbr rfl,bmtxe ; Setze Beenden-Flag zurück
cbi pctrl,bcts ; CTS wieder einschalten
ldi ZH,HIGH(2*txtcur) ; Gib Cursor an SIO aus
ldi ZL,LOW(2*txtcur)
rcall txtext
cpi XL,LOW(srtx) ; Schon Zeichen eingegeben?
breq loop ; Nein, schlafen legen bis SIO-RX kommt
ldi ZH,HIGH(srtx) ; Gepufferte Zeichen auf Cursor-
ldi ZL,LOW(srtx) ; zeile ausgeben an SIO-TX
stoptx1:
ld rmp,z+ ; Zeichen aus Puffer lesen
rcall txch ; an SIO senden
cp ZL,XL ; Schon alle ausgegeben?
brcs stoptx1 ; Weiter ausgeben
rjmp loop ; Alles ausgegeben, schlafen legen
;
; Getpar holt menuegesteuert Parameter vom User
;
getpar:
ldi rmp,siorxtx ; Rx-Interrupts abschalten
out UCR,rmp ; reiner Polling-Betrieb
getpar0:
rcall calctc ; Rechne aktuelle Parameter um
getpara:
rcall txpar ; Gib die Parameter aus
getparb:
ldi ZH,HIGH(2*txtmenue) ; Gib Menue aus
ldi ZL,LOW(2*txtmenue)
rcall txtext
rcall rxch ; Hole ein Zeichen von SIO
cpi rmp,chesc ; Ende-Zeichen ESCAPE?
brne getpar1 ; Nein, mach weiter im Menue
cbr rfl,bmesc ; Setze Menue-Flag zurück

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.asm (1 of 2)1/20/2009 7:50:19 PM


http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.asm

rjmp start1 ; Ende, starte fast alles neu


getpar1:
cpi rmp,'s' ; Speichern gewählt?
brne getpar1a
rjmp getpars ; geh zum Speichern
getpar1a:
cpi rmp,'l' ; Lesen gewählt?
brne getpar1b
rjmp getparl ; geh zum Lesen
getpar1b:
cpi rmp,'d' ; Default-Werte gewählt?
brne getpar1c
rjmp getpard ; Setze Default Werte
getpar1c:
cpi rmp,'x' ; Testtext gewählt?
brne getpar1d
rjmp getparx
getpar1d:
ldi ZH,HIGH(2*txtf); Zeiger auf Frequenzzeile
ldi ZL,LOW(2*txtf) ; im Menue
cpi rmp,'f' ; Frequenzeingabe gewählt?
brne getpar1e
rjmp getpar2 ; ja, hole Zahl
getpar1e:
ldi ZH,HIGH(2*txtg); Geschwindigkeitseingabe
ldi ZL,LOW(2*txtg) ; Zeiger setzen
cpi rmp,'g' ; Geschwindigkeitseingabe gewählt?
brne getpar1f
rjmp getpar2 ; ja, hole Zahl
getpar1f:
ldi ZH,HIGH(2*txtt) ; Zeiger auf Texteingabe
ldi ZL,LOW(2*txtt)
cpi rmp,'t' ; Texteingabe gewählt?
brne getpar0 ; Nein, gib dem User noch mal das Menue
getpar2: ; Hole eine Zahlen- oder Texteingabe in den Puffer
push rmp ; wird noch gebraucht (gewählter Menuepunkt)
rcall txch ; Echo char an SIO zurück
ldi rmp,chcr ; Mache neue Zeile
rcall txch
rcall txtext ; Gib den ausgewählten Menuetext aus
ldi XH,HIGH(srtx) ; Empfangspuffer auf Anfang
ldi XL,LOW(srtx)
getpar3:
rcall rxch ; Hole char von SIO
st x+,rmp ; in Puffer
out UDR,rmp ; Echo an SIO
cpi rmp,chcr ; Ende der Eingabe?
brne getpar3 ; Weiter mit Eingabe
clr rmp ; String Nullterminieren
st x,rmp
pop rmp ; Menuepunkt wieder vom Stapel holen
cpi rmp,'t' ; Texteingabe gewählt?
breq getpara ; Ja, schon fertig, gib die Parameter aus
push rmp ; Wird weiterhin gebraucht (Menuepunkt)
rcall lese16 ; ASCII-Zahl im Puffer in binär
; in R1:R0 umwandeln
pop rmp ; Menuepunkt wieder herstellen
brcs getpare ; Fehler in Zahl, Fehlermeldung ausgeben
cpi rmp,'f' ; Frequenz gewählt?
brne getparg ; Nein, Geschwindigkeit gewählt!
mov rmp,R1 ; Zahl zu groß?
cpi rmp,0x10 ; Frequenz > 4095 Hz?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,0x01 ; Frequenz < 256 Hz?
brcs getpark ; Fehlermeldung Zahl zu niedrig
sts sfrq,R0 ; Zahl ok, übertragen
sts sfrq+1,R1
rjmp getpar0 ; Rechne Parameter neu aus und gebe aus
getparg: ; Neue Geschwindigkeit eingegeben
tst R1 ; Zahl <256?
brne getparh ; Nein, Fehlermeldung Zahl zu groß
mov rmp,R0
cpi rmp,201 ; Zahl >200?
brcc getparh ; Fehlermeldung Zahl zu groß
cpi rmp,10 ; Zahl <10?
brcs getpark ; Zahl zu niedrig
sts sbpm,R0 ; Zahl ok, übertragen
rjmp getpar0 ; Beginne Neu mit Berechnung und Ausgabe
getpars: ; Speichern der eingestellten Werte im EEPROM
rcall ewrite ; Alles übertragen
ldi ZH,HIGH(2*txteepw); Meldung ausgeben
ldi ZL,LOW(2*txteepw)
rcall txtext
rjmp getparb ; Menuepunkte ausgeben und weiter
getparl: ; Lesen der Werte aus dem EEPROM
rcall ecopy ; Alles ins SRAM übertragen
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpard: ; Default-Werte setzen
ldi ZH,HIGH(sfrq) ; Zeiger auf Frequenz
ldi ZL,LOW(sfrq)
ldi rmp,LOW(cfrq) ; LSB Default-Frequenz setzen
st z+,rmp ; in SRRAM-Speicher
ldi rmp,HIGH(cfrq) ; MSB Default-Frequenz setzen
st z+,rmp ; in SRAM-Speicher
ldi rmp,cbpm ; Default-Geschwindigkeit
st z+,rmp ; in SRAM-Speicher
rcall getdeftext ; Default-text in Speicher
rjmp getpar0 ; Alle Parameter neu berechnen und weiter
getpare: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtzahl) ; Fehler in Zahl
ldi ZL,LOW(2*txtzahl)
rcall txtext
rjmp getpara
getpark: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txtklein) ; Zahl zu niedrig
ldi ZL,LOW(2*txtklein)
rcall txtext
rjmp getpara
getparh: ; Fehlermeldung ausgeben
ldi ZH,HIGH(2*txthoch) ; Zahl zu hoch
ldi ZL,LOW(2*txthoch)
rcall txtext
rjmp getpara
getparx: ; Test-Text ausgeben (nur in der STK-Version!)
ldi XH,HIGH(srtx) ; Zeiger X auf SRAM-Text
ldi XL,LOW(srtx)
ldi ZH,HIGH(2*tsttext) ; Zeiger Z auf Testtext
ldi ZL,LOW(2*tsttext)
getparx1:
lpm ; Lese Zeichen
st x+,R0 ; Zeichen in SRAM-Puffer
adiw ZL,1 ; nächstes Zeichen
tst R0 ; Zeichen eine Null?
brne getparx1 ; weiter mit Zeichen
rjmp getpara ; fertig
getdeftext: ; Default text in Speicher ab Z
ldi rmp,'<' ; Verkehrsanfang, eingefügt 2313=>8515
st z+,rmp
ldi rmp,10 ; Testtext in Speicher
mov R0,rmp ; in Zähler
getdeftext1:
ldi rmp,'P' ; Paris
st z+,rmp
ldi rmp,'A'
st z+,rmp
ldi rmp,'R'
st z+,rmp
ldi rmp,'I'
st z+,rmp
ldi rmp,'S'
st z+,rmp
ldi rmp,' '
st z+,rmp
dec R0
brne getdeftext1
sbiw ZL,1 ; Eins zurück
ldi rmp,'>'
st z+,rmp
ldi rmp,chcr ; Textpuffer mit Carriage Return
st z+,rmp
clr rmp ; und Nullterminator
st z,rmp ; entleeren
ret ; eingefügt bis hier 2313=>8515
;
; Warte auf char von der SIO mit Echo
;
rxch:
in rmp,USR ; Lese Control register
sbrs rmp,RXC ; Character vorhanden?
rjmp rxch ; Noch nicht, weiter warten
in rmp,UDR ; Lese character aud Datenregister
ret ; und zurück
;
; Sende text character in rmp an SIO mit Prüfung
;
txch:
push rmp ; Rette Zeichen auf Stapel
txch1:
in rmp,USR ; Senderegister leer?
sbrs rmp,UDRE ; Ist das UDRE-Bit gesetzt
rjmp txch1 ; Nein, weiter warten
pop rmp ; Hole Zeichen vom Stapel
out UDR,rmp ; Character senden
cpi rmp,chcr ; Nach Carriage Return noch ein
brne txch2 ; Linefeed?
ldi rmp,chlf ; auch den noch senden!
rcall txch
ldi rmp,chcr ; und Zeichen wieder herstellen
txch2:
ret
;
; Morsecode der ASCII-Zeichen 0x20 bis 0x5F
; unteres Byte = Code (0=Punkt, 1=Strich)
; oberes Byte = Anzahl Punkte/Striche
; Bit 7 = 1: Leerzeichen
;
morse:
; Zeichen 20 .. 2F
.DB 0b11100000,0b10000011 ; Blank
.DB 0b01000000,5 ; ! = Warten
.DB 0b01001000,6 ; "
.DB 0b11011000,5 ; # = ~n
.DB 0b01101000,5 ; $ = á, °a
.DB 0b01000000,5 ; % = é
.DB 0b00000000,0 ; & = nicht benutzt
.DB 0b01111000,6 ; '
.DB 0b10110000,5 ; (
.DB 0b10110100,6 ; )
.DB 0b00000000,0 ; * = nicht benutzt
.DB 0b00010100,6 ; + = Spruchende
.DB 0b11001100,6 ; ,
.DB 0b10000100,6 ; -
.DB 0b01010100,6 ; .
.DB 0b10010000,5 ; /
;Zeichen 30 .. 3F
.DB 0b11111000,5 ; 0
.DB 0b01111000,5 ; 1
.DB 0b00111000,5 ; 2
.DB 0b00011000,5 ; 3
.DB 0b00001000,5 ; 4
.DB 0b00000000,5 ; 5
.DB 0b10000000,5 ; 6
.DB 0b11000000,5 ; 7
.DB 0b11100000,5 ; 8
.DB 0b11110000,5 ; 9
.DB 0b11100000,6 ; :
.DB 0b10101000,6 ; ;
.DB 0b10101000,5 ; < = Verkehrsanfang
.DB 0b10001000,5 ; =
.DB 0b01010000,5 ; > = Verkehrsende
.DB 0b00110000,6 ; ?
;Zeichen 40 .. 4F
.DB 0b11110000,4 ; @ = ch
.DB 0b01000000,2 ; A
.DB 0b10000000,4 ; B
.DB 0b10100000,4 ; C
.DB 0b10000000,3 ; D
.DB 0b00000000,1 ; E
.DB 0b00100000,4 ; F
.DB 0b11000000,3 ; G
.DB 0b00000000,4 ; H
.DB 0b00000000,2 ; I
.DB 0b01110000,4 ; J
.DB 0b10100000,3 ; K
.DB 0b01000000,4 ; L
.DB 0b11000000,2 ; M
.DB 0b10000000,2 ; N
.DB 0b11100000,3 ; O
;Zeichen 50 .. 5F
.DB 0b01100000,4 ; P
.DB 0b11010000,4 ; Q
.DB 0b01000000,3 ; R
.DB 0b00000000,3 ; S
.DB 0b10000000,1 ; T
.DB 0b00100000,3 ; U
.DB 0b00010000,4 ; V
.DB 0b01100000,3 ; W
.DB 0b10010000,4 ; X
.DB 0b10110000,4 ; Y
.DB 0b11000000,4 ; Z
.DB 0b01010000,4 ; [ = Ä
.DB 0b11100000,4 ; \ = Ö
.DB 0b00110000,4 ; ] = Ü
.DB 0b00000000,8 ; ^ = Irrung
.DB 0b00110100,6 ; _
morseende:
.DW morseende-morse ; Prüfzahl, muss 0x0040 sein
;
; Testtext, nur in der STK-Version implementiert!
tsttext:
.DB "<THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 1234567890>",chcr,cnul
ChkT:
.DW ChkT
;
; Texte für die serielle Schnittstelle
; Hinweis: Die chk-Werte sind zum Überprüfen im Listing
; eingefügt. Es gibt einen Bug im AVR-Assembler von ATMEL,
; der zu falschen Adressen führt, wenn bestimmte Kombina-
; tionen von Byte-Konstanten verwendet werden. Dieser Bug
; ist seit zwei Jahren gemeldet und noch immer nicht besei-
; tigt! Teilweise sind die abenteuerlichen Konstruktionen
; in dieser Liste zur Umgehung dieses Bugs verwendet.
;
; Eingangsmeldung zu Beginn
txtid:
.DB chff,chcr
.DB "+---------------------------------+",chcr
.DB "| Morseprogramm (C)2002 by DG4FAC |",chcr
.DB "+---------------------------------+",chcr
.DB cnul,cnul
chk1:
.DW chk1 ; für Assembler Bug
; Text für Parameterliste
txtpar1:
.DB chcr,'E',"ingestellte Parameter:",chcr,'*'
txtf:
.DB "NF-Frequenz (256..4095 Hz) = ",cnul
chk2: ; Bug-Check
.DW chk2
txtpar2:
.DB " Hz ",chcr,'*'
txtg:
.DB "Geschwindigkeit (10..200 BpM) = ",cnul
chk3: ; Bug-Check
.DW chk3
txtpar3:
.DB " BpM",chcr,' ',"ccm = ",cnul,cnul
chk4: ; Bug-Check
.DW chk4
txtpar4:
.DB ", Ints (kurz) = ",cnul,cnul
chk5: ; Bug-Check
.DW chk5
txtpar5:
.DB ", Ints (lang) = ",cnul,cnul
chk6: ; Bug-Check
.DW chk6
txtpar6:
.DB chcr,'*'
txtt:
.DB "Text = ",cnul
chk7: ; Bug-Check
.DW chk7
txtcur:
.DB chcr,'=','>',cnul
chk8: ; Bug-Check
.DW chk8
txtmenue:
.DB "Einstellungen: f=NF-Frequenz, g=Geschwindigkeit,"
.DB " t=Text, s=Speichern,",chcr
.DB " l=Lesen, d=Default, x=Test, ESC=Ende! ",chcr
.DB "(f,g,t,s,l,d,x,ESC) => ",cnul
chk9: ; Bug-Check
.DW chk9 ; Prüfzahl für Assembler-Bug
txtzahl:
.DB chcr,'F',"ehler in Ziffer oder Zahl bzw. Zahl zu gross!",cnul
chk10: ; Bug-Check
.DW chk10 ; Prüfzahl für Assembler-Bug
txtklein:
.DB chcr,'*',"* Zahl zu niedrig! **",cnul,cnul
chk11: ; Bug-Check
.DW chk11 ; Prüfzahl für Assembler-Bug
txthoch:
.DB chcr,'*',"* Zahl zu hoch! **",cnul,cnul
chk12: ; Bug-Check
.DW chk12 ; Prüfzahl für Assembler-Bug
txteepw:
.DB chcr,'P',"arameter ins EEPROM geschrieben.",chcr,cnul
chk13: ; Bug-Check
.DW chk13
;
; Copyright-Info
.DB "C(2)00 2ybD 4GAF C"
;
; Programm-Code Ende
;
; ******************************************
; * EEPROM-Inhalt mit Default beginnt hier *
; ******************************************
;
.ESEG
.ORG 0x0000
;
efrq:
; Die Default-NF-Frequenz
.DW cfrq
ebpm:
; Die Default-Geschwindigkeit in BpM
.DB cbpm
etxt:
; Dieser Text wird zu Beginn ausgegeben
.DB "hello!"
.DB chcr,cnul
etxte:
;
; Copyright-Info
;
.DB "(C)2002 by DG4FAC"
;
; Ende des EEPROM-Segmentes
;

http://www.avr-asm-tutorial.net/cq-dl/teil4/Cw01_500.asm (2 of 2)1/20/2009 7:50:19 PM


Gerd's AVR Assembler

Pfad: Home => AVR-Assembler

Gerd's AVR Assembler


● To the english page
● Zur deutschen Seite

Assembler Caller Software for Windows


● To the english page
● Zur deutschen Seite

http://www.avr-asm-tutorial.net/gavrasm/index.html1/20/2009 7:50:22 PM
http://www.avr-asm-tutorial.net/gavrasm/v22/DosRead.Txt

gavrasm on DOS
--------------

If you get the error message "No DPMI" when trying to


start gavrasm.exe on a DOS machine, please download
the DOS package "Base files (program and units,
basego32.zip" (or the full package, if you like),
of Free Pascal from the website

http://www.freepascal.org

Unpack the files and move the file "cwsdpmi.exe" to


a directory, which is in the path of your DOS.

This should resolve the problem. Unfortunately I


cannot verify this, because I don't have a DOS machine
here.

Remember: Using the DOS-version in a Win-Environment


requires that all filenames (e.g. of include files)
have to be compatible with the 8.3 format.

Gerhard Schmidt, info (at) avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gavrasm/v22/DosRead.Txt1/20/2009 7:50:23 PM
http://www.avr-asm-tutorial.net/gavrasm/v22/instr.asm

;
; Complete instruction set
; test file for gavrasm compiler
;
; If testhigh is 0 the lower range of values is tested,
; if testhigh is 1 the upper range of values is tested
;
.EQU testhigh=0
;
.IF testhigh==0 ; Lower range of values
.DEF r = R0
.DEF rh = R16
.DEF rd = R24
.DEF rf = R16
.DEF rm = R0
.EQU p = 0
.EQU pl = 0
.EQU b = 0
.EQU k63 = 0
.EQU k127 = 0
.EQU k255 = 0
.EQU k4095 = 0
.EQU k65535 = 0
.EQU k4M = 0
.ELSE ; Upper range of values
.DEF r = R31
.DEF rh = R31
.DEF rd = R30
.DEF rf = R23
.DEF rm = R30
.EQU p = 63
.EQU pl = 31
.EQU b = 7
.EQU k63 = 63
.EQU k127 = -63
.EQU k255 = 255
.EQU k4095 = -2048
.EQU k65535 = 65535
.EQU k4M = 4194303
.ENDIF
;
instruct:
adc r,r
add r,r
adiw rd,k63
and r,r
andi rh,k255
asr r
bclr b
bld r,b
.IF testhigh==0
brbc b,-64
brbs b,-64
brcc -64
brcs -64
.ELSE
brbc b,+63
brbs b,+63
brcc +63
brcs +63
.ENDIF
break
.IF testhigh==0
breq -64
brge -64
brhc -64
brhs -64
brid -64
brie -64
brlo -64
brlt -64
brmi -64
brne -64
brpl -64
brsh -64
brtc -64
brts -64
brvc -64
brvs -64
.ELSE
breq +63
brge +63
brhc +63
brhs +63
brid +63
brie +63
brlo +63
brlt +63
brmi +63
brne +63
brpl +63
brsh +63
brtc +63
brts +63
brvc +63
brvs +63
.ENDIF
bset b
bst r,b
call k4M
cbi pl,b
cbr rh,k255
clc
clh
cli
cln
clr r
cls
clt
clv
clz
com r
cp r,r
cpc r,r
cpi rh,k255
cpse r,r
dec r
eicall
eijmp
elpm
elpm r,Z
elpm r,Z+
eor r,r
fmul rf,rf
fmuls rf,rf
fmulsu rf,rf
icall
ijmp
in r,p
inc r
jmp k4M
ld r,X
ld r,X+
ld r,-X
ld r,Y
ld r,Y+
ld r,-Y
ld r,Z
ld r,Z+
ld r,-Z
ldd r,Y+k63
ldd r,Z+k63
ldi rh,k255
lds r,k65535
lpm
lpm r,Z
lpm r,Z+
lsl r
lsr r
mov r,r
movw rm,rm
mul r,r
muls rh,rh
neg r
nop
or r,r
ori rh,k255
out p,r
pop r
push r
.IF testhigh==0
rcall -2048
.ELSE
rcall +2047
.ENDIF
ret
reti
.IF testhigh==0
rjmp -2048
.ELSE
rcall +2047
.ENDIF
rol r
ror r
sbc r,r
sbci rh,k255
sbi pl,b
sbic pl,b
sbis pl,b
sbiw rd,k63
sbr rh,k255
sbrc r,b
sbrs r,b
sec
seh
sei
sen
ser rh
ses
set
sev
sez
sleep
spm
spm Z+
st X,r
st X+,r
st -X,r
st Y,r
st Y+,r
st -Y,r
st Z,r
st Z+,r
st -Z,r
std Y+k63,r
std Z+k63,r
sts k65535,r
sub r,r
subi rh,k255
swap r
tst r
wdr
.EXIT

This is the complete instruction set in one file.

http://www.avr-asm-tutorial.net/gavrasm/v22/instr.asm1/20/2009 7:50:25 PM
http://www.avr-asm-tutorial.net/gavrasm/instr_doswin.asm

;
; Complete instruction set
; test file for gavrasm compiler
;
; If testhigh is 0 the lower range of values is tested,
; if testhigh is 1 the upper range of values is tested
;
.EQU testhigh=0
;
.IF testhigh==0 ; Lower range of values
.DEF r = R0
.DEF rh = R16
.DEF rd = R24
.DEF rf = R16
.DEF rm = R0
.EQU p = 0
.EQU pl = 0
.EQU b = 0
.EQU k63 = 0
.EQU k127 = 0
.EQU k255 = 0
.EQU k4095 = 0
.EQU k65535 = 0
.EQU k4M = 0
.ELSE ; Upper range of values
.DEF r = R31
.DEF rh = R31
.DEF rd = R30
.DEF rf = R23
.DEF rm = R30
.EQU p = 63
.EQU pl = 31
.EQU b = 7
.EQU k63 = 63
.EQU k127 = -63
.EQU k255 = 255
.EQU k4095 = -2048
.EQU k65535 = 65535
.EQU k4M = 4194303
.ENDIF
;
instruct:
adc r,r
add r,r
adiw rd,k63
and r,r
andi rh,k255
asr r
bclr b
bld r,b
.IF testhigh==0
brbc b,-64
brbs b,-64
brcc -64
brcs -64
.ELSE
brbc b,+63
brbs b,+63
brcc +63
brcs +63
.ENDIF
break
.IF testhigh==0
breq -64
brge -64
brhc -64
brhs -64
brid -64
brie -64
brlo -64
brlt -64
brmi -64
brne -64
brpl -64
brsh -64
brtc -64
brts -64
brvc -64
brvs -64
.ELSE
breq +63
brge +63
brhc +63
brhs +63
brid +63
brie +63
brlo +63
brlt +63
brmi +63
brne +63
brpl +63
brsh +63
brtc +63
brts +63
brvc +63
brvs +63
.ENDIF
bset b
bst r,b
call k4M
cbi pl,b
cbr rh,k255
clc
clh
cli
cln
clr r
cls
clt
clv
clz
com r
cp r,r
cpc r,r
cpi rh,k255
cpse r,r
dec r
eicall
eijmp
elpm
elpm r,Z
elpm r,Z+
eor r,r
fmul rf,rf
fmuls rf,rf
fmulsu rf,rf
icall
ijmp
in r,p
inc r
jmp k4M
ld r,X
ld r,X+
ld r,-X
ld r,Y
ld r,Y+
ld r,-Y
ld r,Z
ld r,Z+
ld r,-Z
ldd r,Y+k63
ldd r,Z+k63
ldi rh,k255
lds r,k65535
lpm
lpm r,Z
lpm r,Z+
lsl r
lsr r
mov r,r
movw rm,rm
mul r,r
muls rh,rh
neg r
nop
or r,r
ori rh,k255
out p,r
pop r
push r
.IF testhigh==0
rcall -2048
.ELSE
rcall +2047
.ENDIF
ret
reti
.IF testhigh==0
rjmp -2048
.ELSE
rcall +2047
.ENDIF
rol r
ror r
sbc r,r
sbci rh,k255
sbi pl,b
sbic pl,b
sbis pl,b
sbiw rd,k63
sbr rh,k255
sbrc r,b
sbrs r,b
sec
seh
sei
sen
ser rh
ses
set
sev
sez
sleep
spm
st X,r
st X+,r
st -X,r
st Y,r
st Y+,r
st -Y,r
st Z,r
st Z+,r
st -Z,r
std Y+k63,r
std Z+k63,r
sts k65535,r
sub r,r
subi rh,k255
swap r
tst r
wdr
.EXIT

This is the complete instruction set in one file.

http://www.avr-asm-tutorial.net/gavrasm/instr_doswin.asm1/20/2009 7:50:27 PM
http://www.avr-asm-tutorial.net/gavrasm/instr_linux.asm

;
; Complete instruction set
; test file for gavrasm compiler
;
; If testhigh is 0 the lower range of values is tested,
; if testhigh is 1 the upper range of values is tested
;
.EQU testhigh=0
;
.IF testhigh==0 ; Lower range of values
.DEF r = R0
.DEF rh = R16
.DEF rd = R24
.DEF rf = R16
.DEF rm = R0
.EQU p = 0
.EQU pl = 0
.EQU b = 0
.EQU k63 = 0
.EQU k127 = 0
.EQU k255 = 0
.EQU k4095 = 0
.EQU k65535 = 0
.EQU k4M = 0
.ELSE ; Upper range of values
.DEF r = R31
.DEF rh = R31
.DEF rd = R30
.DEF rf = R23
.DEF rm = R30
.EQU p = 63
.EQU pl = 31
.EQU b = 7
.EQU k63 = 63
.EQU k127 = -63
.EQU k255 = 255
.EQU k4095 = -2048
.EQU k65535 = 65535
.EQU k4M = 4194303
.ENDIF
;
instruct:
adc r,r
add r,r
adiw rd,k63
and r,r
andi rh,k255
asr r
bclr b
bld r,b
.IF testhigh==0
brbc b,-64
brbs b,-64
brcc -64
brcs -64
.ELSE
brbc b,+63
brbs b,+63
brcc +63
brcs +63
.ENDIF
break
.IF testhigh==0
breq -64
brge -64
brhc -64
brhs -64
brid -64
brie -64
brlo -64
brlt -64
brmi -64
brne -64
brpl -64
brsh -64
brtc -64
brts -64
brvc -64
brvs -64
.ELSE
breq +63
brge +63
brhc +63
brhs +63
brid +63
brie +63
brlo +63
brlt +63
brmi +63
brne +63
brpl +63
brsh +63
brtc +63
brts +63
brvc +63
brvs +63
.ENDIF
bset b
bst r,b
call k4M
cbi pl,b
cbr rh,k255
clc
clh
cli
cln
clr r
cls
clt
clv
clz
com r
cp r,r
cpc r,r
cpi rh,k255
cpse r,r
dec r
eicall
eijmp
elpm
elpm r,Z
elpm r,Z+
eor r,r
fmul rf,rf
fmuls rf,rf
fmulsu rf,rf
icall
ijmp
in r,p
inc r
jmp k4M
ld r,X
ld r,X+
ld r,-X
ld r,Y
ld r,Y+
ld r,-Y
ld r,Z
ld r,Z+
ld r,-Z
ldd r,Y+k63
ldd r,Z+k63
ldi rh,k255
lds r,k65535
lpm
lpm r,Z
lpm r,Z+
lsl r
lsr r
mov r,r
movw rm,rm
mul r,r
muls rh,rh
neg r
nop
or r,r
ori rh,k255
out p,r
pop r
push r
.IF testhigh==0
rcall -2048
.ELSE
rcall +2047
.ENDIF
ret
reti
.IF testhigh==0
rjmp -2048
.ELSE
rcall +2047
.ENDIF
rol r
ror r
sbc r,r
sbci rh,k255
sbi pl,b
sbic pl,b
sbis pl,b
sbiw rd,k63
sbr rh,k255
sbrc r,b
sbrs r,b
sec
seh
sei
sen
ser rh
ses
set
sev
sez
sleep
spm
st X,r
st X+,r
st -X,r
st Y,r
st Y+,r
st -Y,r
st Z,r
st Z+,r
st -Z,r
std Y+k63,r
std Z+k63,r
sts k65535,r
sub r,r
subi rh,k255
swap r
tst r
wdr
.EXIT

This is the complete instruction set in one file.

http://www.avr-asm-tutorial.net/gavrasm/instr_linux.asm1/20/2009 7:50:28 PM
Akkuloader with an ATmega16

Path: Home => Akkuloader

Akkuload - a microprocessor controlled loader


for accu cells
To the english description
Important message: A serious bug has been detected, please follow the instructions on the download
page!

Akkuload - ein Mikroprossor-gesteuertes


Ladegerät für Akkuzellen
Zur deutschen Beschreibung
In der Software wurde ein ernster Fehler gefunden. Bitte die Hinweise auf der Download-Seite
beachten!

©2005 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/akkuload/index.html1/20/2009 7:50:29 PM
Akkuloader with an ATmega16

Path: Home => Akkuloader


Zur deutschen Beschreibung

Akkuload - a microprocessor controlled loader for


accu cells
Changes

Changes on May 2, 2005

In version 1 of March 2005, a serious bug causes a false calculation of the load current. The load current is
roughly half the value than is selected and displayed. To avoid this bug, download the new version of akkucalc.
asm as of May 5, 2005, re-assemble and re-program. (Thanks for uncovering this bug to Sebastian Mazur).

Description
The acculoader loads up
to four single accu cells
with predefined currents
between 5 mA and 220
mA (max. up to 350 mA
in a single channel). The
characteristics and all
necessary parameters are
selectable for each of the
four channels separatly, so
that mixed loading of
different cells is possible
with no limitations. The
load characteristics are
preselected, the
microprocessor measures
and controls currents and
capacities. The control
over the loader can either
take place with a serial
RS232 interface and a
terminal program like
Hyperterminal or by three keys. Output and control uses a 4-line-LCD.

The characteristica and the load history of up to 32 accumulators are storable internally, so that the necessary
parameters (load capacity, currents, etc.) can be selected very quick. The number of full loads with nominal
capacity is stored and automatically updated each time a load ends.

Using the RS232 interface, all informations are readable and all functions can be performed. By using the
monitoring mode all measured values are traced and can be copied to a textfile. These values can be used to
display the load characteristics via PC software.

Functions
Akkuload uses an ATMEL AVR ATmega16 at an internal clock of 8 Mcs/s. Attached to the processor are:

● four pulsewidth generators for the control over the load current,
● four outputs for initiating the unload cycle,
● four AD converter channels for measuring the accu cell voltages,
● four AD converter channels for measuring the four load currents,
● three inputs for the keys, in part combined with
● four LED outputs for signalling the loading state of the channels,
● two serial ports (RXD/TXD) for communication over the RS232 interface,
● 10 Port-In- and Outputs for control over the LCD display, combined with
● four in- and outputs for the In-System-Programming-Interface.

Download
Hint: the switch schematic in the 2005 version had a bug in the wiring of channel 3. This is corrected in the
below refernced version of 2007.

● schematics
❍ microprocessor part, GIF-format

❍ analog part, GIF-format

❍ analog part, PDF-format

● commented source code files


❍ All five asm files in one zipfile

❍ Akkuload main routines

❍ Calculation routines

❍ Key input routines

❍ LCD routines

❍ UART communication routines

©2005..2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/akkuload/en/index.html1/20/2009 7:50:36 PM
Akkulader mit einem ATmega16

Path: Home => Akkuloader


Zur englischen Beschreibung

Akkuload - ein Mikroprossor-gesteuertes Ladegerät


für Akkuzellen
Änderungen

Neue Version vom 26.6.05

In der Routine akkuuart.asm ist der Text über den Zustand des Monitoring falsch ausgegeben. Betroffen ist nur
der Betrieb mit RS232/SIO. Der Fehler ist korrigiert.

Neue Version vom 2.5.05

In der Routine akkucalc.asm vom März führt ein Fehler dazu, dass der angezeigte Strom doppelt so groß
erscheint als er tatsächlich ist. Entsprechend falsch sind auch alle abgeleiteten Größen (Ladekapazität etc.). Bitte
die Version von akkucalc.asm vom 2.5.05 verwenden! (Danke an den Entdecker, Sebastian Mazur)

Beschreibung
Der Akkulader lädt maximal vier kleine Akkus einzeln mit wählbaren Strömen zwischen 5 mA und 220 mA
(max. bis ca. 350 mA in einem einzelnen Kanal). Das Laden und alle Einstellungen dazu erfolgt individuell für
jeden einzelnen Akku, gemischte Bestückung der vier Kanäle ist daher ohne Einschränkung möglich. Der
Ladevorgang jedes einzelnen der maximal vier Akkus wird vorgewählt und von einem Mikroprozessor gemessen
und überwacht, der Ströme und Ladekapazitäten misst und korrigiert. Die Bedienung des Geräts erfolgt entweder
über die serielle Schnittstelle eines Rechners oder über drei Tasten. Die Bedienung und die Ausgabe der
aktuellen Werte erfolgt über eine vierzeilige LCD-Anzeige.

Die Charakteristika und die Ladegeschichte von maximal 32 Akkus sind intern speicherbar, so dass über die
Nummer des Akkus rasch die nötigen Einstellungen (Ladekapazität, Ströme, etc.) vorgenommen sind. Die
Anzahl Volladungen der einzelnen Akkus mit Nennkapazität werden gespeichert und automatisch nach
Abschluss des Ladevorganges aktualisiert.

Über die SIO-Schnittstelle können alle Informationen ausgelesen und alle Funktionen bedient werden. Im
Monitoring-Modus können die Messwerte mitgeschrieben und später mittels Software auf dem PC ausgewertet
werden.

Funktionsweise
Das Gerät wird durch einen ATMEL-AVR ATmega16 mit einem internen Takt von 8 MHz gesteuert. An den
Prozessor sind angeschlossen:

● vier pulsweiten-getaktete Ausgänge für die Steuerung des Ladestroms,


● vier Ausgänge zur Ansteuerung des Entladevorgangs,
● vier AD-Wandler-Kanäle zur Überwachung der Spannung der vier Akkus,
● vier AD-Wandler-Kanäle zur Überwachung des Stroms beim Entladen und Laden der vier Akkus,
● drei Eingänge für die Bedientasten, teilweise kombiniert mit
● vier LED-Ausgängen zur Anzeige des Ladezustands,
● zwei serielle Ports für die Kommunikation über die RS232- Schnittstelle,
● 10 Port-Ein- und Ausgänge für die Ansteuerung der LCD-Anzeige, kombiniert mit
● vier Ein-/Ausgängen für die Programmierschnittstelle zur In-System-Programmierung des Prozessors.

Download
Hinweis: Im Schaltbild des Analogteils in der Version aus 2005 waren die AD-Wandler-Anschlüsse von Kanal 3
vertauscht. Dieser Fehler ist in der unten referenzierten Version korrigiert.

● Alles in einem: Ausführliche Beschreibung, Schaltbilder, ein Anwendungsbeispiel, kommentierte


Software in einer Datei zum Download (1,2 MB).
● Schaltpläne
❍ Mikroprozessor-Teil, GIF-Format

❍ Analogteil, GIF-Format

❍ Analogteil, PDF-Format

● Kommentierte Assembler-Quelldateien
❍ Alle fünf Quelldateien in einem Zipfile

❍ Akkuload Hauptprogramm

❍ Berechnungsroutinen

❍ Tastatureingaben

❍ LCD-Routinen

❍ UART Kommunikationsroutinen

©2005..2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/akkuload/de/index.html1/20/2009 7:50:37 PM
http://www.avr-asm-tutorial.net/akkuload/schematic/akkulader_proc.gif

http://www.avr-asm-tutorial.net/akkuload/schematic/akkulader_proc.gif1/20/2009 7:50:40 PM
http://www.avr-asm-tutorial.net/akkuload/schematic/switch_schem.gif

http://www.avr-asm-tutorial.net/akkuload/schematic/switch_schem.gif1/20/2009 7:50:43 PM
BC879

8k2 470 B1
C1/C2
+
270µ -AGND
1N E2
4148
10k
BC879

3k3 B1 C1/C2
3Ω3
10k 1%
E2

A0
10k
+5V 100n +A0
GND BC879

8k2 470 B1
C1/C2
+
270µ
1N E2
4148
10k
BC879

3k3 B1 C1/C2
3Ω3
10k 1%
E2
20 19
A1
10k
+A1

BC879

8k2 470 B1 C1/C2


+
270µ
2 1 E2
1N
4148
10k
BC879

3k3 B1 C1/C2
3Ω3
10k 1%

Akku-Load E2

A2
I/O-Unit 10k
+A2
(C)2005/2007 by Gerh.Schmidt
info@avr-asm-tutorial.net
BC879

8k2 470 B1
C1/C2
+
270µ
1N E2
4148
10k
BC879

3k3 B1 C1/C2
3Ω3
10k 1%
E2

A3
10k
+A3
http://www.avr-asm-tutorial.net/akkuload/de/akkuload.asm

; **************************************************************
; * Akkulader Version 0.1 for ATmega16 @ 8 MHz Takt *
; * (C)2005 by Gerh.Schmidt info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "m16def.inc"
;
; Konstanten
;
.EQU fclock = 8000000 ; Processortaktfrequenz
.EQU baud = 9600 ; Serielle Schnittstelle Baudrate
.EQU cUartTime = 5 ; Alle 5 Minuten die Systemzeit an das UART
.EQU cKeyRep = 5 ; Anzahl Durchläufe bis Tastendruck akzeptiert wird
.EQU cUnlVol = 1000 ; Standard-Entladespannung in mV
;
; Register Definitionen
;
; R0 wird für diverse Operationen verwendet
; R1:R0 Als Doppelregister bei Rechenoperationen verwendet
; R3:R2 dto.
; R6:R5:R4 Dreifachregister bei Rechenoperationen
.DEF rKeyLst = R7 ; Letzte gedrückte Taste
.DEF rKeyRep = R8 ; Zähler für Tastenwiederholung
;.DEF rAdcV = R9 ; Betriebsspannungsmaske für ADC
.DEF rPwmC = R10 ; PWM Zähler
.DEF rPwm1S = R11 ; PWM Schaltwert für Kanal 1
.EQU cPwm1S = 11 ; (Pointerwert für Kanal 1)
.DEF rPwm2S = R12 ; PWM Schaltwert für Kanal 2
.DEF rPwm3S = R13 ; PWM Schaltwert für Kanal 3
.DEF rPwm4S = R14 ; PWM Schaltwert für Kanal 4
.DEF rSreg = R15 ; Sicherung von SREG bei Interrupts
.DEF rmp = R16 ; Multipurpose Register
.DEF rimp = R17 ; Multipurpose Register bei Interrupts
.DEF rimp1 = R18 ; Multipurpose Register bei Interrupts
.DEF rFlg = R19 ; Multipurpose Flag Register (siehe unten)
.DEF rFlgD = R20 ; Anzeige Flag Register (siehe unten)
.DEF rPwmOut= R21 ; Wert für die PWM-Ausgabe
; Frei R22..R23
.DEF rChCL = R24 ; Kanalzähler für ADC-Messungen, LSB
.DEF rChCH = R25 ; dto., MSB
; X (R27:R26) für verschiedene Zwecke außerhalb von Interrupts
; Y (R29:R28) bei Interrupts für Messauswertung verwendet
; Z (R31:R30) für verschiedene Zwecke außerhalb von Interrupts
;
; Bit-Definitionen für rFlg
.EQU bUartRxLine = 7 ; Eine vollständige Zeile über UART empfangen
.EQU bLcdOk = 6 ; LCD-Anzeige angeschlossen und ok
; nicht benutzt: Bits 3, 4 und 5
.EQU bMin = 2 ; Timer hat 1 Minute erreicht
.EQU b32m = 1 ; Timer Interrupt 4 Secunden, 32 ADC-Messungen komplett
.EQU b64Hz = 0 ; Timer Interrupt 64 Hz Tick
;
; Bit-Definitionen für das Anzeigeflag rFlgD
;
.EQU bUHex = 7 ; Zeige Ergebnisse in Hex über UART an (Debug)
.EQU bUMoni = 6 ; Zeige aktive Kanäle über UART an
.EQU bURdy = 5 ; Ergebnisse komplett für die UART-Ausgabe
.EQU bLRdy = 4 ; Ergebnisse komplett für die LCD-Ausgabe
.EQU bLcd3 = 3 ; Zeile 4 der LCD ist frei verwendbar
.EQU bLcd2 = 2 ; Zeile 3 der LCD ist frei verwendbar
.EQU bLcd1 = 1 ; Zeile 2 der LCD ist frei verwendbar
.EQU bLcd0 = 0 ; Zeile 1 der LCD ist frei verwendbar
;
;
; Berechnete Konstanten
;
.EQU cTC1Prsc = 8 ; TC1 Vorteiler-Wert
.EQU cTC1Div = fClock / cTC1Prsc / 64 ; 64 Interrupts pro Sekunde
.EQU cTC1CompB = 50 ; Timer-Wert für den Start der ADC-Umwandlung
.EQU cStartAdc = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADC Enable, Clock=128
.EQU cRestartAdc = cStartAdc | (1<<ADSC) ; Starte ADC-Umwandlung
.EQU cAdcV = 1<<REFS0 ; ADC-Referenzspannung auf 5V
.EQU cEepMax = 512/16 ; Maximale Anzahl gespeicherter Akku-Id's im EEPROM
.EQU cCr = $0D ; Wagenrücklauf-Zeichen für UART
.EQU cLf = $0A ; Zeilenvorschub-Zeichen für UART
;
; SRAM Positionen
;
; UART SRAM Variablen
.EQU sUartRxBp = $0060 ; UART Rx Pufferzeiger
.EQU sUartRxBs = $0061 ; Uart Rx Pufferanfang
.EQU sUartRxBe = $007E ; Uart Rx Pufferende
.EQU sUartCurCh = $007F ; Aktueller Kanal für UART-Ein-/Ausgabe
; Sollwerte der Ladekanäle
.EQU sCh1UV = $0080 ; Kanal 1, Entladespannung Abschaltwert
.EQU sCh1LC = $0082 ; Kanal 1, Ladestrom in mA
.EQU sCh1LW = $0084 ; Kanal 1, Ladekapazität in mAh
.EQU sCh1MC = $0086 ; Kanal 1, Erhaltungsladestrom in mA
.EQU sCh2UV = $0088 ; Kanal 2, dto.
.EQU sCh2LC = $008A ; Kanal 2, dto.
.EQU sCh2LW = $008C ; Kanal 2, dto.
.EQU sCh2MC = $008E ; Kanal 2, dto.
.EQU sCh3UV = $0090 ; Kanal 3, dto.
.EQU sCh3LC = $0092 ; Kanal 3, dto.
.EQU sCh3LW = $0094 ; Kanal 3, dto.
.EQU sCh3MC = $0096 ; Kanal 3, dto.
.EQU sCh4UV = $0098 ; Kanal 4, dto.
.EQU sCh4LC = $009A ; Kanal 4, dto.
.EQU sCh4LW = $009C ; Kanal 4, dto.
.EQU sCh4MC = $009E ; Kanal 4, dto.
; Messwerte vom ADC
.EQU sAdcE1 = $00A0 ; ADC Messergebnisse, geradzahlige Kanäle (Akkus)
.EQU sAdcO1 = $00A8 ; dto., ungeradzahlige Kanäle (Ladewiderstand)
.EQU sAdcE4 = $00B0 ; ADC Summe für 4 Sekunden, geradzahlige Kanäle
.EQU sAdcO4 = $00B8 ; dto., ungeradzahlige Kanäle
.EQU sAdcU = $00C0 ; berechnete Spannungen, geradzahlige und ungeradzahlige
.EQU sAdcI = $00D0 ; berechnete Ladeströme in mA
.EQU sAdcC = $00D8 ; berechnete Kapazitäten in mAh (LSB,MSB)
.EQU sAdcLL1= $00E0 ; berechnete Kapazitäten in mAh (LLSB), Kanal 1
.EQU sAdcAI1= $00E1 ; Akku Id, Kanal 1
; Kanalsteuerung
.EQU sState = $00E8 ; Aktueller Status der Kanäle, Bits 44332211
; 00=abgeschaltet, 01:entladen, 10:laden, 11:erhalten
.EQU sTimeM = $00E9 ; Systemzeit, Minuten (0, 15, 30, 45)
.EQU sTimeH = $00EA ; dto., Stunden
.EQU sTimeD = $00EB ; dto., Tage
.EQU sLcdCs = $00EC ; LCD Cursor Position
; Tasteneingabe
.EQU sKeyNC = $00ED ; Dezimalzahl Eingabeposition
.EQU sKeyNW = $00EE ; Dezimalzahl Ein- und Ausgabewort
.EQU sKeyNM = $00F0 ; Dezimalzahl Maximalwert
.EQU sKeyJR = $00F2 ; Sprungadresse für Dezimalzahleingabeende
.EQU sKeyJS = $00F4 ; Sprungadresse bei Abbruch der Dezimalzahleingabe
.EQU sKeyJ1 = $00F6 ; Sprungadresse bei Taste 1 gedrückt
.EQU sKeyJ2 = $00F8 ; dto., Taste 2
.EQU sKeyJ3 = $00FA ; dto., Taste 3
.EQU sKeyCh = $00FC ; Aktueller Kanal für Tasteneingabe (0, 1..4)
; LED-Ausgabe
.EQU sLedC = $00FD ; LED-Zähler
.EQU sLed1 = $00FE ; LED Kanal 1 Vergleichswert
.EQU sLed2 = $00FF ; dto., Kanal 2
.EQU sLed3 = $0100 ; dto., Kanal 3
.EQU sLed4 = $0101 ; dto., Kanal 4
; EEPROM-Lese- und Schreibpuffer
.EQU sEepB = $0102 ; EEPROM Puffer für einen Akku-ID-Record, 16 Bytes
.EQU sEAId = $0102 ; EEPROM Akku Id
.EQU sESize = $0103 ; EEPROM Akkugröße = A0..A3 (Mignon, Baby, AA, AAA)
.EQU sENCL = $0104 ; EEPROM Nennkapazität LSB
.EQU sENCM = $0105 ; dto., MSB
.EQU sENLL = $0106 ; EEPROM Anzahl der Volladungen, LSB
.EQU sENLM = $0107 ; dto., MSB
.EQU sENRL = $0108 ; EEPROM Restkapazität in mAh, LSB
.EQU sENRM = $0109 ; dto., MSB
.EQU sEATxt = $010A ; Textteil der Akku-Definition
.EQU sENul = $0112 ; Null-Zeichen als Stopwert
.EQU sEANm = $0113 ; Anzahl der im EEPROM gespeicherten korrekten IDs
;
; Nächste freie SRAM-Position: $0114
;
;
; Reset- und Interrupt-Vektoren
; (Vektoren beim ATmega16 sind Doppelworte!)
;
.CSEG
.ORG $0000
rjmp main ; Reset Vektor
nop
reti ; INT0 Vektor
nop
reti ; INT1 Vektor
nop
reti ; TC2Comp Vektor
nop
reti ; TC2Ovf Vektor
nop
reti ; TC1Capt Vektor
nop
rjmp TC1CmpAIsr ; TC1CompA Vektor
nop
rjmp TC1CmpBIsr ; TC1CompB Vektor
nop
reti ; TC1Ovf Vektor
nop
rjmp TC0OvfIsr ; TC0Ovf Vektor
nop
reti ; SPI, STC Vektor
nop
rjmp SioRxCIsr; USARTRxC Vektor
nop
reti ; USARTUdre Vektor
nop
reti ; USARTTxc Vektor
nop
reti ; ADC Vektor
nop
reti ; EE_RDY Vektor
nop
reti ; ANA_COMP Vektor
nop
reti ; TWI Vektor
nop
reti ; INT2 Vektor
nop
reti ; TC0Comp Vektor
nop
reti ; SPM_RDY Vektor
nop
;
; TC1 Compare A Int Serviceroutine
; (Liest das Resultat einer ADC-Messung und speichert es)
;
TC1CmpAIsr:
in rSreg,SREG ; Sichere SREG
sbr rFlg,1<<b64Hz ; Setze 64 Tick Flagge
mov rimp,rChCL ; Prüfe Zähler
andi rimp,1 ; ungerader oder gerader Kanal?
brne TC1CmpAIsrO ; ungerader Kanal
; Gerader Kanal
mov rimp,rChCL ; Prüfe Zähler
andi rimp,0xF8 ; Isoliere Zähler ohne die Kanalnummer
brne TC1CmpAIsrE1 ; Kein Neustart
; TC1 hat 32 Messungen beendet, startet neu
in rimp,ADCL ; Lese ADC LSB
st Y,rimp ; Speichere im SRAM
in rimp,ADCH ; Lese ADC MSB
std Y+1,rimp ; Speichere im SRAM
rjmp TC1CmpAIsrE3
TC1CmpAIsrE1: ; kein Neustart
cpi rimp,0xF8 ; letzte Messung im aktuellen Kanal?
breq TC1CmpAIsrE2 ; Ja, addiere die letzte Messung
; Normale Messung, addiere zur Summe
in rimp1,ADCL ; Lese Ergebnis vom ADC, LSB
ld rimp,Y ; Lese bisherige Summe aus SRAM
add rimp,rimp1 ; Addiere Ergebnis
st Y,rimp ; Speichere im SRAM
in rimp1,ADCH ; Lese Ergebnis vom ADC, MSB
ldd rimp,Y+1 ; lese gespeicherte Summe im SRAM, MSB
adc rimp,rimp1 ; Addiere Messergebnis zur Summe
std Y+1,rimp ; Speichere MSB im SRAM
rjmp TC1CmpAIsrE3
TC1CmpAIsrE2: ; die letzte Messung der Messreihe
in rimp1,ADCL ; Lese Ergebnis vom ADC, LSB
ld rimp,Y ; Lese gespeicherte Summe, LSB
add rimp,rimp1 ; Addiere zum Ergebnis
std Y+16,rimp ; Speichere den Summenwert im SRAM, LSB
in rimp1,ADCH ; Lese Ergebnis vom ADC, MSB
ldd rimp,Y+1 ; Lese gespeicherte Summe, MSB
adc rimp,rimp1 ; Addiere zum Ergebnis MSB
std Y+17,rimp ; Speichere den Summenwert im SRAM, MSB
TC1CmpAIsrE3:
adiw rChCL,1 ; Erhöhe den Kanalzähler
mov rimp,rChCL ; Kopiere LSB des Kanalzählers
andi rimp,0x07 ; isoliere Kanalnummer des nächsten Kanals
ori rimp,cAdcV ; Setze die Referenzspannungsbits
out ADMUX,rimp ; Wähle den nächsten MUX-Kanal des ADC an
out SREG,rSreg ; Stelle SREG wieder her
reti
;
TC1CmpAIsrO: ; ungerader Kanal
mov rimp,rChCL ; Kopiere LSB Kanalzähler
andi rimp,0xF8 ; isoliere alles bis auf die Kanalnummer
brne TC1CmpAIsrO1 ; kein Neustart
; TC1 hat 32 Messungen beendet, startet neu
in rimp,ADCL ; Lese ADC, LSB
std Y+8,rimp ; Speichere im SRAM (überschreibt alte Summe)
in rimp,ADCH ; Lese ADC, MSB
std Y+9,rimp ; Speichere im SRAM (überschreibt alte Summe)
rjmp TC1CmpAIsrO3
TC1CmpAIsrO1: ; ungerader Kanal, kein Neustart
cpi rimp,0xF8 ; Letzte Messung im Kanal?
breq TC1CmpAIsrO2 ; Ja, addiere den letzten Wert
; Normale Messung, addiere zur Summe und speichere
in rimp1,ADCL ; Lese ADC, LSB
ldd rimp,Y+8 ; Lese gespeicherte Summe aus SRAM, LSB
add rimp,rimp1 ; addiere zum Ergebnis, LSB
std Y+8,rimp ; Speichere Summe im SRAM, LSB
in rimp1,ADCH ; Lese ADC, MSB
ldd rimp,Y+9 ; Lese gespeicherte Summe aus SRAM, MSB
adc rimp,rimp1 ; addiere zum Ergebnis, MSB
std Y+9,rimp ; Speichere Summe im SRAM, MSB
rjmp TC1CmpAIsrO3
TC1CmpAIsrO2: ; Ungerader Kanal, letzte Messung im Kanal
in rimp1,ADCL ; Lese ADC, LSB
ldd rimp,Y+8 ; Lese bisherige Summe, LSB
add rimp,rimp1 ; Addiere zum Ergebnis, LSB
std Y+24,rimp ; Speichere das letzte Summenergebnis, LSB
in rimp1,ADCH ; Lese ADC, MSB
ldd rimp,Y+9 ; Lese bisherige Summe, MSB
adc rimp,rimp1 ; addiere zum Ergebnis, MSB
std Y+25,rimp ; Speichere das letzte Summenergebnis, MSB
TC1CmpAIsrO3:
adiw YL,2 ; zeige auf nächste Position im SRAM
adiw rChCL,1 ; nächster Kanal
mov rimp,rChCL ; Kopiere Zähler, LSB
andi rimp,0x07 ; Isoliere nächsten Kanal
brne TC1CmpAIsrO4 ; Nicht Kanal 1
ldi YH,HIGH(sAdcE1) ; Setze Pointer zurück auf Kanal 1
ldi YL,LOW(sAdcE1)
TC1CmpAIsrO4:
ori rimp,cAdcV ; Setze die Referenzspannungs-Bits
out ADMUX,rimp ; Wähle nächsten ADC-MUX-Kanal
tst rChCL ; Alles am Anfang?
brne TC1CmpAIsrO5 ; nein
sbr rFlg,1<<b32m ; Setze die Flagge für 32 Zyklen komplett
TC1CmpAIsrO5:
out SREG,rSreg ; Stelle SREG wieder her
reti
;
; TC1 Compare B Interrupt Serviceroutine
;
TC1CmpBIsr:
sbi ADCSR,ADSC ; Starte ADC-Messzyklus
reti
;
; TC0 Overflow Interrupt Serviceroutine
;
Tc0OvfIsr:
in rsreg,SREG ; Sichere SREG
inc rPwmC ; Erhöhe PWM-Zähler
brne Tc0OvfIsr1 ; nicht Null, weiter
mov rimp,rPwmOut ; Kopiere die bisherige Kanalausgabe
andi rimp,0xF0 ; Erhalte die vier obersten Bits (Entladebits)
mov rPwmOut,rimp ; Setze die Kanalausgabe auf Null
ldi rimp,0xF0 ; Maskiere die vier obersten Bits
eor rimp,rPwmOut ; Invertiere die vier obersten Bits
swap rimp ; vertausche die oberen und unteren Bits
or rPwmOut,rimp ; Setze die Kanalausgabe (1 für aktive Kanäle)
TC0OvfIsr1:
cp rPwmC,rPwm1S ; Vergleiche den Kanalzähler mit Sollwert Kanal 1
brne TC0OvfIsr2 ; nicht gleich, springe
cbr rPwmOut,1 ; PWM-Bit für Kanal 1 abschalten
TC0OvfIsr2:
cp rPwmC,rPwm2S ; Vergleiche den Kanalzähler mit Sollwert Kanal 2
brne TC0OvfIsr3 ; nicht gleich, springe
cbr rPwmOut,2 ; PWM-Bit für Kanal 2 abschalten
TC0OvfIsr3:
cp rPwmC,rPwm3S ; Vergleiche den Kanalzähler mit Sollwert Kanal 3
brne TC0OvfIsr4 ; nicht gleich, springe
cbr rPwmOut,4 ; PWM-Bit für Kanal 3 abschalten
TC0OvfIsr4:
cp rPwmC,rPwm4s ; Vergleiche den Kanalzähler mit Sollwert Kanal 4
brne TC0OvfIsr5 ; nicht gleich, springe
cbr rPwmOut,8 ; PWM-Bit für Kanal 4 abschalten
TC0OvfIsr5:
out PORTC,rPwmOut ; Auf Port C ausgeben
out SREG,rsreg ; Stelle SREG wieder her
reti
;
; Uart RxC Interrupt Serviceroutine
;
SioRxCIsr:
in rSreg,SREG ; Sichere SReg
in rimp,UCSRA ; Lese UART Fehlerbits
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; Isoliere Fehler-Bits
in rimp,UDR ; Lese empfangenes Zeichen vom UART
breq SioRxCIsr1 ; kein Fehler, springe
ldi rimp,'*' ; Zeige einen Empfangsfehler an
sbrs rFlg,bUartRxLine ; Ist der Zeilenpuffer blockiert?
out UDR,rimp ; Echo des Zeichens an UART
rjmp SioRxCIsr4 ; Ignoriere das Zeichen
SioRxCIsr1:
sbrc rFlg,bUartRxLine ; Zeilenpuffer blockiert?
rjmp SioRxCIsr4 ; Ja, ignoriere das Zeichen
out UDR,rimp ; Echo des Zeichens an UART
push ZH ; Sichere Z-Register
push ZL
ldi ZH,HIGH(sUartRxBs) ; Position für nächstes Zeichen, MSB
lds ZL,sUartRxBp ; dto., LSB
st Z+,rimp ; speichere Zeichen im Puffer
cpi ZL,LOW(sUartRxBe+1) ; Ende des Puffers erreicht?
brcc SioRxCIsr2 ; Pufferüberlauf
sts sUartRxBp,ZL ; Speichere nächste Pufferposition
SioRxCIsr2:
cpi rimp,cCr ; Wagenrücklauf?
brne SioRxCIsr3 ; Nein, mach weiter
ldi rimp,cLf ; Echo Zeilenvorschub an UART
out UDR,rimp ; in Ausgaberegister des UART
sbr rFlg,(1<<bUartRxLine) ; Setze Zeile-Komplett-Flag
SioRxCIsr3:
pop ZL ; Stelle Z-Register wieder her
pop ZH
SioRxCIsr4:
out SREG,rSreg ; Stelle SREG wieder her
reti ; Return vom Interrupt
;
;*************************** Hauptprogram *******************
;
; Beginn des Hauptprogramms, Init der Hardware und der SRAM-Variablen
;
main:
ldi rmp,HIGH(RAMEND) ; Stelle Stapelzeiger ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; Initiiere Register und SRAM
clr rFlg ; Flaggen löschen
clr rFlgD ; Anzeigeflaggen löschen
ldi rFlgD,0x0F ; LCD-Zeilenzugriff ermöglichen
; Initiiere die Ports
clr rmp ; Port A alle Bits Eingang
out DDRA,rmp
ldi rmp,0xFF ; Port C alle Bits Ausgang
out DDRC,rmp
ldi rmp,0xF2 ; Port D Bits 7..4 und 1 als Ausgänge
out DDRD,rmp
; Initiiere die Tasten
rcall KeyInit ; Init-Routine für Tasten aufrufen
; Initiiere die LEDs
rcall KeyLedInit ; Init-Routine für die LEDs aufrufen
; Statusflaggen und Systemzeit initiieren
clr rmp
ldi ZH,HIGH(sState) ; Statusflagge
ldi ZL,LOW(sState)
st Z+,rmp ; sState
st Z+,rmp ; sTimeM
st Z+,rmp ; sTimeH
st Z+,rmp ; sTimeD
st Z+,rmp ; LCD-Cursorposition
ldi ZH,HIGH(sAdcC) ; Initiiere mAh-Werte
ldi ZL,LOW(sAdcC)
ldi rmp,16 ; 16 Bytes löschen
clr R0
main1:
st Z+,R0 ; Position Null setzen
dec rmp ; nächste Position
brne main1 ; noch welche
ldi ZH,HIGH(sCh1UV) ; Initiiere Akku Sollwerte
ldi ZL,LOW(sCh1UV)
ldi rmp,32
main2:
st Z+,R0 ; auf Null setzen
dec rmp ; nächste Position
brne main2 ; noch welche
sts sUartCurCh,R0 ; Setze UART Kanal auf Null
; Initiiere die EEPROM Liste der Akku-Id's
rcall EpInit ; rufe EEPROM-Init-Routine auf
; Initiiere den UART
call UartInit ; Initiiere UART-Empfang und -Senden
call UartSendOpenText ; Sende den Eröffnungstext
call UartSendCursor ; Sende den Cursor über den UART
; Initiiere die LCD-Anzeige
rcall LcdInit ; Rufe die LCD-Init-Routine auf
; Initiiere die PWM-Kanäle
clr rPwm1S ; Setze den Anfangswert für Kanal 1
clr rPwm2S ; Setze den Anfangswert für Kanal 2
clr rPwm3S ; Setze den Anfangswert für Kanal 3
clr rPwm4S ; Setze den Anfangswert für Kanal 4
clr rPwmOut ; PWM-Ausgabe deaktivieren
; Initiiere die Timer 0 und 1
ldi rmp,HIGH(cTC1Div) ; TC1: Teiler für das 64 Hz-Signal
out OCR1AH,rmp ; MSB zuerst!
ldi rmp,LOW(cTC1Div)
out OCR1AL,rmp ; LSB zuletzt!
ldi rmp,HIGH(cTC1CompB) ; MSB zuerst!
out OCR1BH,rmp
ldi rmp,LOW(cTC1CompB) ; LSB zuletzt!
out OCR1BL,rmp
clr rmp ; TC1: TC1-Mode: keine Ausgabe, kein PWM
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; TC1: CTC und Vorteiler = 8
out TCCR1B,rmp
ldi rmp,(1<<TOIE0)|(1<<OCIE1A)|(1<<OCIE1B) ; TC0 Überlauf und TC1CompA/B Int
out TIMSK,rmp
ldi rmp,1<<CS00 ; Setze TC0 Vorteiler auf 1
out TCCR0,rmp
; Initiiere den ADC
ldi YH,HIGH(sAdcE1) ; Y ist der ADC-Ergebnis-Zeiger
ldi YL,LOW(sAdcE1)
clr rChCH ; Setze Kanalzähler für ADC auf Null
clr rChCL
ldi rmp,cAdcV ; Setze ADC-Referenzspannung und MUX auf Kanal 0
out ADMUX,rmp
ldi rmp,cStartAdc ; Starte ADC, Taktvorteiler=128, keine Interrupts
out ADCSR,rmp
sei ; Ermögliche Interrupts
loop: ; Hauptprogramm-Schleife
; Keinen SLEEP-Mode hier benutzen, da das den ADC-Ablauf stört
tst rFlg ; Irgendeine Flagge gesetzt?
breq loop ; nein, starte Schleife neu, bis was passiert
ldi rmp,LOW(loop) ; Schleifenanfang als Rücksprungadresse auf den Stapel
push rmp
ldi rmp,HIGH(loop)
push rmp
; Prüfe die 64 Hz Tick Flagge von Timer 0
sbrc rFlg,b64Hz ; ein Tick?
rjmp Tick64Hz ; lese Tasten und werte sie aus
; Prüfe ob 32 Messzyklen komplett sind und 4 Sekunden vorüber sind
sbrc rFlg,b32m ; Prüfe 32 Messungen und 4 Sekunden vorüber
rjmp Adc32m ; Springe zur Messauswertung
; Prüfe ob Hexadezimalwerte über das UART ausgegeben werden sollen (Debug)
sbrc rFlgD,bURdy ; Werte Flagge aus
rjmp DisplHex ; Gib Hexwerte über das UART aus (Debug)
; Prüfe ob Ergebnisse über die LCD-Anzeige ausgegeben werden können
sbrc rFlgD,bLRdy ; Prüfe LCD-Werte fertig
rjmp DisplLcd ; rufe LCD-Anzeige-Routine auf
; Prüfe ob eine Minute vorüber ist
sbrc rFlg,bMin ; Werte Minuten-Flagge aus
rjmp Minute ; Springe zur Minutenausgabe
; Prüfe ob eine über das UART empfangene Zeile komplett ist
sbrs rFlg,bUartRxLine ; Werte Rx-Zeile-Komplett-Flagge aus
ret ; nein
jmp UartRxLine ; ja, beantworte empfangene UART-Zeile
;
; Ein 64 Hz Tick
;
Tick64Hz:
cbr rFlg,1<<b64Hz ; Setze Flagge zurück
rcall KeyLeds ; rufe die LED-Auswertungsroutine auf
rjmp Keys ; rufe die Tastenauswertung auf
;
; Binde die Berechnungsroutinen ein
;
.INCLUDE "akkucalc.asm"
;
; Binde die Tastenauswertungsroutinen ein
;
.INCLUDE "akkukey.asm"
;
; Binde die LCD-Anzeigenroutinen ein
;
.INCLUDE "akkulcd.asm"
;
; Binde die UART-Routinen ein
;
.INCLUDE "akkuuart.asm"
;
; Ende des Code-Segments
;
; EEPROM-Segment, Initiiere meine Akkus
;
.ESEG
;
; Akku-Id-Definition:
; Byte 1: Id-Nummer, muss von 1 an in fortgesetzter Reihenfolge sein
; Byte 2: Bauart der Zelle, A0(Mono), A1(Baby), A2(AA), A3(AAA)
; Byte 2 und 3: Nennkapazität in mAh, LSB and MSB
; Byte 4 and 5: Anzahl der Volladungen mit Nennkapazitär, LSB and MSB
; Byte 6 and 7: Ladekapazität, verbleibende mAh der letzten Ladung
; Byte 8 to 16: Textbeschreibung der Zelle, exakt 8 Buchstaben lang
;
; Akku 1: AAA, NiMH, Conrad 250185
.DB 0x01,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 2: AAA, NiMH, Conrad 250185
.DB 0x02,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 3: AAA, NiMH, Conrad 250185
.DB 0x03,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 4: AAA, NiMH, Conrad 250185
.DB 0x04,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 5: AA, NiMH, Pixcell Camera
.DB 0x05,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 6: AA, NiMH, Pixcell Camera
.DB 0x06,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 7: AA, NiMH, Pixcell Camera
.DB 0x07,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 8: AA, NiMH, Pixcell Camera
.DB 0x08,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 9: AA, NiMH, Conrad Voltcraft
.DB 0x09,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 10: AA, NiMH, Conrad Voltcraft
.DB 0x0A,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 11: AA, NiMH, Conrad Voltcraft
.DB 0x0B,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 12: AA, NiMH, Conrad Voltcraft
.DB 0x0C,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Ende der Akkumulator Id-Definitionen
;

http://www.avr-asm-tutorial.net/akkuload/de/akkuload.asm1/20/2009 7:50:51 PM
http://www.avr-asm-tutorial.net/akkuload/de/akkucalc.asm

; *******************************************************************
; * Include Routine fuer Akkuload, Berechnungs- und Anzeigeroutinen *
; * (C)2005 by Gerh.Schmidt, info@avr-asm-tutorial.net *
; *******************************************************************
;
; ************** EEPROM Init, Lesen und Schreiben ******************
;
; Initiiert den EEPROM-Speicher und stellt gespeicherte Id's fest
;
EpInit:
clr ZH ; Z ist EEPROM-Lesezeiger
clr ZL
clr R0 ; R0 ist Z•ler
EpInit1:
sbic EECR,EEWE ; Warte auf Schreib-Ende
rjmp EpInit1 ; Warte weil Schreib-Bit gesetzt
inc R0 ; n•hste Akku-Id
ldi rmp,cEepMax+1 ; Maximalanzahl Id's
cp R0,rmp ; vergleiche
brcc EpInit4 ; Ende erreicht
out EEARL,ZL ; EEPROM-Leseadresse setzen
out EEARH,ZH
sbi EECR,EERE ; EEPROM-Lesebit setzen
EpInit2:
sbic EECR,EERE ; warte auf Lesen ok
rjmp EpInit2 ; warte weiter
in rmp,EEDR ; Lese Akku-Id-Nummer
cp rmp,R0 ; vergleiche mit aktueller Nummer
brne EpInit4 ; nicht richtig, beende
adiw ZL,1 ; n•hstes Byte im EEPROM
out EEARL,ZL ; EEPROM-Lese-Adresse setzen
out EEARH,ZH
sbi EECR,EERE ; Read Enable setzen
EpInit3:
sbic EECR,EERE ; warte auf Lesen ok
rjmp EpInit3 ; warte weiter
in rmp,EEDR ; Lese Typangabe
cpi rmp,0xA0 ; muss zwischen hex A0 und A3 sein
brcs EpInit4 ; kleiner als A0, beenden
cpi rmp,0xA4 ; gr•er als A3?
brcc EpInit4 ; gr•er als A3, beenden
adiw ZL,15 ; n•hste EEPROM-Position
rjmp EpInit1 ; weiter
EpInit4:
dec R0 ; speichere Anzahl korrekter Akku-Id's
sts sEaNm,R0
ret
;
; Lese den EEPROM-Inhalt der Akku-Id in rmp in den SRAM-Puffer
;
EpRead:
dec rmp ; Startet mit Id=1
mov ZL,rmp ; Kopiere nach Z
clr ZH ; MSB auf Null, Adresse mit 16 multiplizieren
lsl ZL ; *2
rol ZH
lsl ZL ; *4
rol ZH
lsl ZL ; *8
rol ZH
lsl ZL ; *16
rol ZH
ldi XH,HIGH(sEepB) ; X ist SRAM-Puffer-Zeiger
ldi XL,LOW(sEepB)
EpRead1:
sbic EECR,EEWE ; warte auf Schreibende
rjmp EpRead1
out EEARH,ZH ; gib EEPROM-Adresse aus
out EEARL,ZL
sbi EECR,EERE ; Setze Read Enable
EpRead2:
sbic EECR,EERE ; Warte auf Lese-Ende
rjmp EpRead2
in rmp,EEDR ; Lese Byte
st X+,rmp ; Speichere im SRAM-Puffer
adiw ZL,1 ; n•hstes Byte im EEPROM
mov rmp,ZL ; Teste auf Ende
andi rmp,0x0F ; letzte vier Bits = Null?
brne EpRead1 ; Lese weiteres Byte
ret
;
; Schreibe den Pufferinhalt im SRAM in das EEPROM
;
EpWrite:
ldi XH,HIGH(sEepB) ; X ist der SRAM-Puffer-Zeiger
ldi XL,LOW(sEepB)
ld rmp,X ; Lese die ID-Nummer
dec rmp ; Id's starten mit Id=1
mov ZL,rmp ; Kopiere nach Z
clr ZH ; MSB leeren, EEPROM-Adresse mit 16 multiplizieren
lsl ZL ; *2
rol ZH
lsl ZL ; *4
rol ZH
lsl ZL ; *8
rol ZH
lsl ZL ; *16
rol ZH
EpWrite1:
sbic EECR,EEWE ; warte auf Schreibende
rjmp EpWrite1
out EEARH,ZH ; gib EEPROM-Schreibadresse aus
out EEARL,ZL
ld rmp,X+ ; Lese Byte aus SRAM-Puffer
out EEDR,rmp ; Schreibe ins EEPROM-Datenregister
cli ; Stop Interrupts
sbi EECR,EEMWE ; Setze Schreibmode Enable
sbi EECR,EEWE ; Setze Write Enable
sei ; erm•liche Interrupts wieder
adiw ZL,1 ; n•hste Adresse im EEPROM
mov rmp,ZL ; Test auf Ende
andi rmp,0x0F ; Letzte vier Bits = Null?
brne EpWrite1 ; Schreibe noch weiter Bytes
ret
;
; Prfe Akku-Id und addiere die Ladekapazit• zur gespeicherten Id im EEPROM
; R0 ist der Kanal, erh•t denm Inhalt von R0 und R1!
;
EpStore:
rcall GetAkkuId ; Lese die Id des aktuellen Kanals
tst rmp ; Id=0?
breq EpStore4 ; ja, beende
lds ZL,sEANm ; Lese die Anzahl Id's im EEPROM
sec ; setze Carry-Flagge
cpc rmp,ZL ; vergleiche mit (Anzahl der Id's+1)
brcc EpStore4 ; gr•er als die Anzahl der gespeicherten Id's
rcall EpRead ; lese die gew•lte Id in das SRAM
ldi ZH,HIGH(sAdcC) ; Zeiger auf die gemessene Ladekapazit• in mAh
ldi ZL,LOW(sAdcC)
add ZL,R0 ; addiere Kanal zur Adresse
add ZL,R0
ld XL,Z+ ; gemessene Ladekapazit• in X lesen
ld XH,Z
lds ZL,sENRL ; Restkapazit• vom Puffer nach Z lesen
lds ZH,sENRM
add ZL,XL ; gemessene Ladekapazit• addieren
adc ZH,XH
lds XL,sENCL ; Nennkapazit• des Akkus in X
lds XH,sENCM
clr rmp ; Z•ler fr Anzahl Volladungen leeren
EpStore1:
cp ZL,XL ; Restkapazit• in Z mit Nennkapazit• in X vergleichen
cpc ZH,XH
brcs EpStore2 ; Restkapazit• kleiner als Nennkapazit•
sub ZL,XL ; subtrahiere Nennkapazit•
sbc ZH,XH
inc rmp ; Erh•e Anzahl der Volladungen
rjmp EpStore1 ; weiter
EpStore2: ; Anzahl der Volladungen ist in rmp, Restkapazit• in Z
sts sENRL,ZL ; Restkapazit• im SRAM-Puffer speichern
sts sENRM,ZH
tst rmp ; eine volle Ladung oder mehr?
breq EpStore3 ; nein
lds ZL,sENLL ; Lese Anzahl Volladungen aus SRAM-Puffer
add ZL,rmp ; addiere zur Anzahl Volladungen
sts sENLL,ZL ; Speichere LSB der Anzahl Volladungen
brcc EpStore3 ; kein •ertrag
lds ZL,sENLM ; erh•e MSB der Anzahl Volladungen
inc ZL
sts sENLM,ZL ; speichere MSB der Anzahl Volladungen
EpStore3: ; SRAM-Puffer ist komplett, speichere
rcall EpWrite ; Schreibe den Puffer ins EEPROM
EpStore4:
ret
;
; *** Wandle die gemessenen Spannungen in dezimal und berechne Strom dezimal ***
;
; Wandle die Summe aus 32 ADC-Messungen in bin•e Spannung um
; Die Summe sd32e ist in R3:R2, das Ergebnis in R3:R2, verwendet R6:R5:R4
; Referenzspannung ist 5V, Umrechnung: U[mV] = s32e * 39 / 256
;
Adc2mV:
mov R4,R2 ; Kopiere s32e nach R6:R5:R4 und multipliziere mit 8
mov R5,R3
clr R6
lsl R4 ; * 2
rol R5
rol R6
lsl R4 ; * 4
rol R5
rol R6
lsl R4 ; * 8
rol R5
rol R6
mov R0,R4 ; Kopiere Zwischenergebnis in rmp:R1:R0, multipliziere mit 32
mov R1,R5
mov rmp,R6
lsl R4 ; * 16
rol R5
rol R6
lsl R4 ; * 32
rol R5
rol R6
add R4,R0 ; * 40, addiere 8-fach und 32-fach = 40-fach
adc R5,R1
adc R6,rmp
clr rmp
sub R4,R2 ; * 39, ziehe Ausgangswert einmal ab = 39-fach
sbc R5,R3
sbc R6,rmp
mov R2,R5 ; / 256, Kopiere die beiden obersten Bytes ins Ergebnis (=/256)
mov R3,R6
ldi rmp,0x80 ; runde das Ergebnis
add rmp,R4
clr rmp
adc R2,rmp
adc R3,rmp
ret
;
; Negativen in positiven bzw. positiven in negativen Wert umwandeln (R3:R2)
;
Negative:
neg R2 ; Zweierkomplement
clr rmp
sbc rmp,R3
mov R3,rmp
ret
;
; Umrechnung der Differenzspannung ber dem Widerstand (in mV) in Strom (mA)
; mV Differenz in R3:R2, Ergebnis in R3:R2
; ADC Referenzspannung ist 5V
; Umrechnung: mA = 11.84 * (s32ungerade - s32gerade) / 256
;
mV2mA:
ldi rmp,0x80 ; teste ob Spannungsdifferenz negativ
and rmp,R3
mov R0,rmp ; Speichere Vorzeichen
breq mV2mA1 ; nicht negativ
; wandle negativ in positiv um
rcall negative
mV2mA1:
mov R4,R2 ; kopiere nach R6:R5:R4
mov R5,R3
clr R6
lsl R4 ; * 2, multipliziere mit zwei
rol R5
rol R6
add R4,R2 ; * 3, addiere Ausgangswert = * 3
adc R5,R3
clr rmp
adc R6,rmp
lsl R4 ; * 6, multipliziere mit zwei = * 6
rol R5
rol R6
lsl R4 ; * 12, multipliziere mit zwei = * 12
rol R5
rol R6
lsr R3 ; R3:R2 / 2, dividiere Ausgangswert / 8
ror R2
lsr R3 ; R3:R2 / 4
ror R2
lsr R3 ; R3:R2 / 8
ror R2
sub R4,R2 ; * 11.88, subtrahiere ein Achtel
sbc R5,R3
sbc R6,rmp
mV2mA3:
mov R2,R5 ; kopiere Ergebnis nach R3:R2, teilen durch 256
mov R3,R6
ldi rmp,0x80 ; runde Ergebnis
add rmp,R4
clr rmp
adc R2,rmp
adc R3,rmp
tst R0 ; prfe negativ
breq mV2mA4 ; nein
rjmp negative ; wandle in negativ um
mV2mA4:
ret
;
; Rechne Strom in mA in Kapazit• in mAh um
; Anfang: R6:R5:R4 enth•t den Strom als 256*I(mA)
; Ende: R3:R2 ist die Ladekapazit• ber 4 Sekunden als 256*mAh
;
mA2mAh:
mov R1,R4 ; Kopiere den Ausgangswert nach R3:R2:R1
mov R2,R5
mov R3,R6
lsr R3 ; dividiere den Strom durch 2
ror R2
ror R1
lsr R3 ; ... durch 4
ror R2
ror R1
; Der Strom in mA, multipliziert mit 64, ist jetzt in R3:R2:R1
clr rmp
add R1,R5 ; addiere den Original-Strom, um 65 * I zu erhalten
adc R2,R6
adc R3,rmp
; Der Strom in mA, multipliziert mit 65, ist jetzt in R3:R2:R1
lsl R4 ; Multiplikation des Ausgangsstroms mit 8
rol R5
rol R6
lsl R4 ; * 4
rol R5
rol R6
lsl R4 ; * 8
rol R5
rol R6
clr rmp ; Runden
rol R4 ; oberstes Bit ins Carry
adc R5,rmp
adc R6,rmp
add R1,R5 ; addiere 8*I zu 65*I = 73*I
adc R2,R6
adc R3,rmp
; Das Ergebnis von 73*I/256 ist jetzt in R3:R2
; Diese Zahl ist gleich der Ladekapazit• in mAh, multipliziert mit 256,
; die in den vergangenen vier Sekunden in den Akku geladen wurden
ret
;
; ********* 32 Messungen der Spannung sind komplett *******
;
; ADC hat 32 Messungen durchgefhrt und aufsummiert
;
Adc32m:
cbr rFlg,1<<b32m ; l•che die 4s Flagge
mov rmp,rChCH ; prfe das MSB des Messz•lers
andi rmp,0x0F ; prfe ob das niedrige Nibble 15 erreicht hat
cpi rmp,15
brcs Adc32m1 ; nein, mach weiter
sbr rFlg,1<<bMin ; setze die Minuten-Flagge
ldi rmp,1 ; korrigiere das niedrige Nibble des MSB des Messz•lers
add rChCH,rmp ; addiere eine Eins
mov rmp,rChCH ; Prfe das obere Nibble des MSB des Messz•lers
andi rmp,0xF0 ; 15 Minuten erreicht?
cpi rmp,0xF0 ; oberes Nibble = 15?
brne Adc32m1 ; nein, mach weiter
ldi rmp,0x10 ; korrigiere MSB
add rChCH,rmp ; addiere 10
; 15 Minuten sind hier vorber, wird nicht weiter ausgewertet
Adc32m1: ; berechne alle Spannungen
ldi ZH,HIGH(sAdcE4); Z zeigt auf die gemessenen Werte
ldi ZL,LOW(sAdcE4)
Adc32m2:
ld R2,Z ; Kopiere den Messwert nach R3:R2
ldd R3,Z+1
rcall Adc2mV ; rechne in mV um
std Z+16,R2 ; speichere Ergebnis im SRAM
std Z+17,R3
adiw ZL,2 ; der n•hste gemessene Wert
cpi ZL,LOW(sAdcE4+16) ; Ende erreicht?
brcs Adc32m2
; Berechne Str•e und Ladekapazit•en
ldi ZH,HIGH(sAdcE4) ; Z zeigt auf die gemessenen Werte
ldi ZL,LOW(sAdcE4)
Adc32m3:
ld R0,Z ; Kopiere die Summe des geraden Messkanals LSB nach R0
ldd R1,Z+1 ; dto., MSB nach R1
ldd R2,Z+8 ; Kopiere die Summe des ungeraden Messkanals LSB nach R2
ldd R3,Z+9 ; dto., MSB nach R3
sub R2,R0 ; subtrahiere LSB
sbc R3,R1 ; dto., MSB
rcall mV2mA ; berechne den Strom in mA
std Z+32,R2 ; Speichere den Strom im SRAM, LSB
std Z+33,R3 ; dto., MSB
rcall mA2mAh ; berechne die mAh aus dem Strom in mA
ldd rmp,Z+48 ; lese das LLSB der mAh in rmp
ldd R0,Z+40 ; lese LSB mAh nach R0
ldd R1,Z+41 ; lese MSB mAh nach R1
add rmp,R2 ; addiere das LLSB
adc R0,R3 ; addiere das LSB
clr R3 ; add das MSB
adc R1,R3
std Z+48,rmp ; speichere das LLSB im SRAM
std Z+40,R0 ; speichere das LSB im SRAM
std Z+41,R1 ; speichere MSB im SRAM
adiw ZL,2 ; n•hster Kanal
cpi ZL,LOW(sAdcE4+8) ; am Ende?
brcs Adc32m3 ; weiter insgesamt vier mal
sbr rFlgD,(1<<bURdy)|(1<<bLRdy) ; Setze die Ergebnis-fertig-Flaggen
ret
;
; ******* Vergleiche den aktuellen Kanal-Status mit dem Sollwert und •dere ****
;
; Addiere den Kanal in R0 zur Adresse in Z
;
ChAdrs:
mov rmp,R0 ; Kanal in rmp kopieren
lsl rmp ; * 2
lsl rmp ; * 4
lsl rmp ; * 8
add ZL,rmp ; und zur Basisadresse in Z addieren
ret
;
; Gibt die Akku-Id vom Kanal in R0 in rmp zurck
;
GetAkkuId:
ldi ZH,HIGH(sAdcAI1) ; Z ist die Adresse des Kanals
ldi ZL,LOW(sAdcAI1)
add ZL,R0 ; addiere Kanal
add ZL,R0
ld rmp,Z ; Lese Id
ret
;
; Setzt die Sollwerte fr die gew•lte Akku-Id
; Erwartet den Kanal in R0
;
IdSetPar:
rcall GetAkkuId ; Lese die Akku-Id des Kanals
tst rmp ; = Null?
breq IdSetPar1 ; ja, tue nichts
lds R1,sEANm ; Lese die Anzahl gespeicherter Id's
sec
cpc rmp,R1 ; vergleiche mit der maximalen Anzahl Id's
brcc IdSetPar1 ; zu gro• tu nichts
rcall EpRead ; Lese die Akku-Id in den SRAM-Puffer
lds R2,sENCL ; Lese die Nennkapazit•, LSB
lds R3,sENCM ; dto., MSB
ldi ZH,HIGH(sCh1UV) ; Z auf die Sollwerte des Kanals setzen
ldi ZL,LOW(sCh1UV)
rcall ChAdrs ; Adresse des Kanals
ldi rmp,LOW(cUnlVol) ; Setze die Entladespannung auf Defaultwert
st Z+,rmp
ldi rmp,HIGH(cUnlVol)
st Z+,rmp
mov R4,R2 ; Berechne den Ladestrom aus der Nennkapazit•
mov R5,R3
lsr R5
ror R4
lsr R5
ror R4
lsr R5
ror R4
st Z+,R4 ; setze den Sollwert Ladestrom
st Z+,R5
add R2,R4 ; Berechne die Ladekapazit• aus der Nennkapazit•
adc R3,R5
st Z+,R2 ; Speichere den Sollwert Ladekapazit•
st Z+,R3
lsl R2 ; Berechne den Erhaltungsstrom aus der Nennkapazit•
rol R3
st Z+,R3 ; Speichere den Sollwert Erhaltungsstrom
clr rmp
st Z+,rmp
IdSetPar1:
ret
;
; Berechne die PWM-Adresse des aktuellen Kanals in R0 in Z
;
PwmAdrs:
ldi ZH,HIGH(cPwm1S) ; Z auf Sollwert von Kanal 1
ldi ZL,LOW(cPwm1S)
add ZL,R0 ; Addiere aktuellen Kanal in R0 zur Adresse
ret
;
; Setze den PWM-Wert in Kanal R0 auf den Wert in rmp und l•che das Unload-Bit
;
PwmSet:
ldi ZL,0xEF ; Unload-Bit fr Kanal 0
mov ZH,R0 ; Kopiere Kanal
PwmSet1:
tst ZH ; ok?
breq PwmSet2 ; ja
sec ; Setze Carry-Bit vor dem Rollen
rol ZL ; n•hsth•eres Bit
dec ZH ; n•hster Kanal
rjmp PwmSet1 ; und wieder von vorn
PwmSet2:
and rPwmOut,ZL ; l•che das Unload-Bit des Kanals
rcall PwmAdrs ; Hole die PWM-Adresse des aktuellen Kanals nach Z
st Z,rmp ; Setze den PWM-Wert fr den Kanal
ret
;
; Setze den Kanal(in R0)status auf den Wert in rmp
;
ChSet:
ldi ZL,0xFC ; Kanalmaske
mov ZH,R0 ; kopiere Kanal
ChSet1:
tst ZH ; Kanal erreicht?
breq ChSet2 ; ja, raus
sec ; Setze Carry-Bit fr das Rollen
rol ZL ; n•hste Kanalmaske
rol ZL
lsl rmp ; schiebe rmp links
lsl rmp
dec ZH ; n•hster Kanal
rjmp ChSet1 ; und wiederholen
ChSet2:
lds ZH,sState ; Lese Statusbits
and ZH,ZL ; l•che Statusbits des Kanals
or ZH,rmp ; Setze die Statusbits des Kanals
sts sState,ZH ; neuen Status speichern
ret
;
; Schalte den Kanal in R0 (von Entladen) auf Laden
;
ToLoad:
ldi rmp,0x02 ; Statusbits fr Laden
rcall ChSet ; Setze Status des Kanals in R0
ldi rmp,150 ; Setze die PWM auf eine mittlere Spannung
rcall PwmSet ; Setze PWM des aktuellen Kanals
rjmp ClearCap ; L•che den Kapazit•swert des Kanals
;
; L•che den Kapazit•swert des Kanals in R0
;
ClearCap:
ldi ZH,HIGH(sAdcC) ; Zeiger auf die Kapazit• des Kanals
ldi ZL,LOW(sAdcC)
add ZL,R0
add ZL,R0
clr rmp
std Z+8,rmp ; l•che LLSB
st Z+,rmp ; l•che LSB
st Z,rmp ; l•che MSB
ret
;
; Vergleiche den Strom im Kanal mit dem Sollwert und korrigiere die PWM
; Erwartet den Kanal in R0 und den Zeiger auf den Sollwert in Z
;
ChCurrent: ; Prfe Strom zu hoch/zu niedrig und korrigiere
rcall ChAdrs ; Adresse in Z auf korrekten Kanal-Sollwert
ld R2,Z+ ; Sollstrom nach R3:R2 laden
ld R3,Z
ldi ZH,HIGH(sAdcI) ; Z auf gemessenen Strom setzen
ldi ZL,LOW(sAdcI)
add ZL,R0 ; Adresse des Kanals
add ZL,R0
ld R4,Z+ ; Ladestrom nach R5:R4 kopieren
ld R5,Z
sub R4,R2 ; vom Sollwert subtrahieren
sbc R5,R3
breq ChCurrent3 ; Strom ist korrekt, raus
brcs ChCurrent1 ; Strom ist zu niedrig, erh•e PWM
rcall PwmAdrs ; Strom zu hoch, erniedrige PWM
ld rmp,Z ; Lese PWM-Wert
dec rmp ; niedriger setzen
brne ChCurrent2 ; ausgeben, wenn nicht Null
inc rmp ; Null erreicht, bleibe bei 1
rjmp ChCurrent2 ; ausgeben
ChCurrent1: ; Strom zu niedrig, erh•en
rcall PwmAdrs ; Adresse des PWM-Registers holen
ld rmp,Z ; PWM-Wert lesen
inc rmp ; erh•en
brne ChCurrent2 ; kein •erlauf
dec rmp ; •erlauf, wieder auf FF setzen
ChCurrent2: ; neuen PWM-Wert speichern
st Z,rmp ; neuen PWM-Wert setzen
ChCurrent3: ; fertig
ret
;
; Prfe die Ist- und Sollwerte der Kan•e
;
ChckStates:
clr R0 ; Kanal 0
lds R1,sState ; Statusbits holen
ChckStates1:
mov rmp,R1 ; Status kopieren
andi rmp,0x03 ; Statusbits des Kanals isolieren
cpi rmp,1 ; Status inaktiv = 0?
brcc ChckStates2 ; Status = 1 oder h•er
clr rmp ; Kanal inaktiv
rcall PwmSet ; Setze PWM auf Null
rjmp ChckStates6 ; n•hster Kanal
ChckStates2: ; Status = 1..3
brne ChckStates3 ; Status=2 oder h•er
ldi ZH,HIGH(sCh1UV) ; Entladen, Z auf Schwellwertspannung
ldi ZL,LOW(sCh1UV)
rcall ChAdrs ; Adresse des Kanals
ld R2,Z+ ; Entladespannung in R3:R2
ld R3,Z
ldi ZH,HIGH(sAdcU) ; Z auf letzte gemessene Spannung
ldi ZL,LOW(sAdcU)
add ZL,R0 ; Adresse des Kanals
add ZL,R0
ld R4,Z+ ; gemessene Spannung in R4:R5
ld R5,Z
sub R4,R2 ; gemessene Spannung < Sollwert
sbc R5,R3
brcc ChckStates6 ; nein, n•hster Kanal
rcall ToLoad ; starte Ladevorgang
rjmp ChckStates6 ; n•hster Kanal
ChckStates3: ; Status ist 2 oder h•er
cpi rmp,2 ; Laden?
brne ChckStates5 ; nein, Erhaltungsladung
ldi ZH,HIGH(sCh1LW) ; Z auf Ladekapazit•-Sollwert
ldi ZL,LOW(sCh1LW)
rcall ChAdrs ; Kanaladresse
ld R2,Z+ ; Sollwert Ladekapazit• in R3:R2
ld R3,Z
ldi ZH,HIGH(sAdcC) ; Z auf Istwert Ladekapazit•
ldi ZL,LOW(sAdcC)
add ZL,R0 ; Kanaladresse
add ZL,R0
ld R4,Z+ ; Istwert Ladekapazit• in R4:R3
ld R5,Z
sub R4,R2 ; Istwert - Sollwert
sbc R5,R3
brcs ChckStates4 ; noch nicht erreicht, weiter laden
ldi rmp,0x03 ; Ende erreicht, setze Status auf Erhaltungsladung
rcall ChSet
ldi rmp,100 ; setze PWM auf niedrigen Wert
rcall PwmSet
rcall EpStore ; Addiere die Ladekapazit• zur Id im EEPROM
rjmp ChckStates6 ; n•hster Kanal
ChckStates4: ; Sollwert Kapazit• nicht erreicht, prfe Strom
ldi ZH,HIGH(sCh1LC) ; Z auf Sollwert Ladestrom
ldi ZL,LOW(sCh1LC)
rcall ChCurrent ; Korrigiere Ladestrom, wenn n•ig
rjmp ChckStates6 ; n•hster Kanal
ChckStates5: ; Erhaltungsladung
ldi ZH,HIGH(sCh1MC) ; Z auf Stromsollwert fr Erhaltungsladung
ldi ZL,LOW(sCh1MC)
rcall ChCurrent ; Korrigiere Ladestrom, wenn n•ig
ChckStates6: ; n•hster Kanal
lsr R1 ; Maske fr n•hsten Kanal
lsr R1
inc R0 ; n•hster Kanal
mov rmp,R0 ; Kanal = 5?
cpi rmp,5
brcc ChckStates7 ; ja, fertig
rjmp ChckStates1 ; weiter
ChckStates7: ; fertig
ret
;
; Prft den Kanalstatus, zeigt das Ergebnis in Hex ber das UART an (Debug)
;
DisplHex:
cbr rFlgD,1<<bURdy ; Display-Flagge l•chen
rcall ChckStates ; Kanalstatus checken
sbrs rFlgD,bUHex ; Hexanzeige-Flagge gesetzt?
ret ; nein, fertig
ldi ZH,HIGH(sAdcE4) ; Ergebnis in Hex anzeigen
ldi ZL,LOW(sAdcE4)
rjmp UartHex16 ; Roh-Messwerte in Hex ausgeben
;
; Spannungen in Zeile 1 des LCD-Displays anzeigen
;
DispVtg:
ldi rmp,0 ; LCD auf Zeile 1
rcall LcdLine
ldi XH,HIGH(sAdcU) ; X als Zeiger auf die Spannungen
ldi XL,LOW(sAdcU)
ldi rmp,'U' ; Zeichen U ausgeben
DispVtg1:
rcall LcdChar ; Zeichen in rmp ausgeben
ld R2,X+ ; Spannung lesen, LSB
ld R3,X+ ; dto., MSB
ldi rmp,LOW(10000) ; mit 10000 mV vergleichen
cp R2,rmp ; zu hoch?
ldi rmp,HIGH(10000)
cpc R3,rmp
brcs DispVtg2 ; Spannung in Ordnung
ldi rmp,'E' ; zu gro•
rcall LcdChar ; EEEEE ausgeben
rcall LcdR0
rcall LcdR0
rcall LcdR0
rjmp DispVtg3
DispVtg2: ; Spannung ok
clr R0 ; fhrende Nullen unterdrcken
rcall LcdDec4 ; vier Dezimalstellen ausgeben
DispVtg3:
ldi rmp,' ' ; Blank ausgeben
cpi XL,LOW(sAdcU+8) ; Ende erreicht?
brcs DispVtg1 ; wiederholen
ret
;
; Str•e in Zeile 2 der LCD anzeigen
;
DispCurr:
ldi rmp,1 ; LCD-Zeile 2
rcall LcdLine ; Zeile ansteuern
ldi XH,HIGH(sAdcI) ; X auf Str•e setzen
ldi XL,LOW(sAdcI)
ldi rmp,'I' ; Stromsymbol ausgeben
DispCurr1:
rcall LcdChar ; Zeichen in rmp an LCD-Display
ld R2,X+ ; lese Strom, LSB
ld R3,X+ ; dto., MSB
mov rmp,R2 ; Null?
or rmp,R3
ldi rmp,' ' ; Leerzeichen ausgeben
breq DispCurr2 ; Null, leer
mov rmp,R3 ; testen ob negativ
rol rmp ; Bit 7 des MSB
ldi rmp,'+' ; +Zeichen in rmp laden
brcc DispCurr2 ; nicht negativ
rcall negative ; Wert in positiven Wert wandeln
ldi rmp,'-' ; -Zeichen in rmp
DispCurr2: ; Vorzeichen ausgeben
rcall LcdChar ; Vorzeichen an LCD
clr R0 ; fhrende Nullen unterdrcken
rcall LcdDec3 ; dreistellige Dezimalzahl ausgeben
ldi rmp,' ' ; Leerzeichen
cpi XL,LOW(sAdcI+8) ; Ende?
brcs DispCurr1 ; nein, n•hster Kanal
ret
;
; Ladekapazit• in mAh in Zeile 3 der LCD ausgeben
;
DispmAh:
ldi rmp,2 ; Zeile 3
rcall LcdLine ; LCD auf Zeile setzen
ldi XH,HIGH(sAdcC) ; X auf mAh setzen
ldi XL,LOW(sAdcC)
ldi rmp,'C' ; C ausgeben
DispmAh1:
rcall LcdChar ; Zeichen in rmp an LCD ausgeben
ld R2,X+ ; lesen mAh LSB
ld R3,X+ ; lesen mAh MSB
mov rmp,R3 ; negativ?
rol rmp ; Vorzeichen in Carry
brcc DispmAh2 ; positiv
rcall negative ; negativ, umwandeln
DispmAh2:
clr R0 ; fhrende Nullen unterdrcken
rcall LcdDec4 ; vierstellig an LCD ausgeben
ldi rmp,' ' ; Leerzeichen
cpi XL,LOW(sAdcC+8) ; Ende?
brcs DispmAh1 ; nein, n•hster Kanal
ret
;
; Ergebnisse auf LCD anzeigen
;
DisplLcd:
cbr rFlgD,1<<bLRdy ; Flagge l•chen
sbrs rFlg,bLcdOk ; LCD vorhanden?
ret ; nein, zurck
sbrs rFlgD,bLcd3 ; Zeile 4 verfgbar?
rjmp DisplLcd1 ; jump over line 4 output
; Ausgaben in Zeile 4, hier nicht benutzt
DisplLcd1:
sbrc rFlgD,bLcd0 ; Zeile 1 der LCD ok fr Ausgabe?
rcall DispVtg ; Spannungen anzeigen
sbrc rFlgD,bLcd1 ; Zeile 2 der LCD verfgbar?
rcall DispCurr ; Str•e anzeigen
sbrc rFlgD,bLcd2 ; Zeile 3 der LCD verfgbar?
rcall DispmAh ; Ladekapazit• anzeigen
rjmp LcdCursor ; Cursor der LCD setzen
;
; Systemzeit eine Minute h•er setzen
;
Time:
ldi ZH,HIGH(sTimeM) ; Z auf Minutenwert
ldi ZL,LOW(sTimeM)
ld rmp,Z ; eine Minute addieren
inc rmp
st Z,rmp
cpi rmp,60 ; Stunde erreicht?
brcs Time1 ; nein, fertig
clr rmp ; Minuten auf Null
st Z+,rmp
ld rmp,Z ; n•hste Stunde
inc rmp
st Z,rmp
cpi rmp,24 ; n•hster Tag?
brcs Time1 ; nein, fertig
clr rmp ; Stunde auf Null
st Z+,rmp
ld rmp,Z ; n•hster Tag
inc rmp
st Z,rmp
cpi rmp,100 ; •erlauf?
brcs Time1 ; nein, weiter
clr rmp ; Tag auf Null
st Z,rmp
Time1:
ret
;
; Ergebnisse ber UART ausgeben
;
Monitor:
lds R1,sState ; Statusbits in R1
clr R5 ; R5 ist Kanalz•ler
Monitor1:
mov rmp,R1 ; Status nach rmp kopieren
andi rmp,0x03 ; Statusbits isolieren
brne Monitor3 ; Status>0
Monitor2: ; Status = Clear, nichts ausgeben
lsr R1 ; n•hster Kanal
lsr R1
inc R5 ; Kanalzahl
ldi rmp,4
cp R5,rmp ; Ende?
brcs Monitor1 ; nein, weiter
ret
Monitor3: ; Status > 0, ausgeben
ldi rmp,'1' ; Sende Kanalnummer
add rmp,R5
rcall UartSendChar
ldi rmp,':' ; Sende :
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'N' ; Sende Id
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi ZH,HIGH(sAdcAI1) ; Z auf Id
ldi ZL,LOW(sAdcAI1)
add ZL,R5
add ZL,R5
ld R2,Z
clr R3
rcall UartSendNmbr
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'S' ; Sende Status
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
mov rmp,R1
andi rmp,0x03
subi rmp,-'0'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcU) ; Sende Spannung, Z auf Spannung
ldi ZL,LOW(sAdcU)
add ZL,R5
add ZL,R5
ld R2,Z+ ; lese Spannung
ld R3,Z+
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'V'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcI) ; Sende Strom, Z auf Strom
ldi ZL,LOW(sAdcI)
add ZL,R5
add ZL,R5
ld R2,Z+
ld R3,Z
mov rmp,R3 ; negativ?
rol rmp
brcc Monitor4
rcall Negative
ldi rmp,'-'
rcall UartSendChar
Monitor4:
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'A'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcC) ; Sende Kapazit•, Z auf Kapazit•
ldi ZL,LOW(sAdcC)

http://www.avr-asm-tutorial.net/akkuload/de/akkucalc.asm (1 of 2)1/20/2009 7:50:54 PM


http://www.avr-asm-tutorial.net/akkuload/de/akkucalc.asm

add ZL,R5
add ZL,R5
ld R2,Z+
ld R3,Z
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'A'
rcall UartSendChar
ldi rmp,'h'
rcall UartSendChar
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp Monitor2 ; n•hster Kanal
;
; Zeit auf LCD ausgeben
;
DisplTimeL:
sbrs rFlg,bLcdOk ; Lcd ok?
ret
sbrs rFlgD,bLcd3 ; Zeile 4 verfgbar?
ret
ldi rmp,3 ; Zeile 4 setzen
mov R1,rmp ; drei Zahlen darzustellen
rcall LcdLine ; Line 4
ldi XH,HIGH(sTimeD+1) ; X auf Zeit in Tagen
ldi XL,LOW(sTimeD+1)
DisplTimeL1:
ld R2,-X ; Zeit lesen
clr R3 ; MSB l•chen
mov R0,R1 ; fhrende Nullen anzeigen
rcall LcdDec2 ; zwei Digits ausgeben
mov rmp,R1
cpi rmp,1 ; : ausgeben?
breq DisplTimeL2 ; nein
ldi rmp,':' ; : anzeigen
rcall LcdChar
DisplTimeL2:
dec R1 ; alle gesendet?
brne DisplTimeL1 ; nein, n•hste Zahl
ldi rmp,' ' ; Leerzeichen anh•gen
rcall LcdChar
rjmp LcdCursor ; Cursor setzen
;
; Zeit prfen und ber UART ausgeben
;
DispTimeU:
ldi rmp,cUartTime ; Minutenintervall der Ausgabe
mov R0,rmp
lds rmp,sTimeM ; Minuten lesen
DispTimeU1:
tst rmp ; Null?
breq DispTimeUd
sub rmp,R0 ; subtrahiere Intervall
brcc DispTimeU1 ; nicht Null, weiter prfen
ret ; nicht ausgeben
;
; Zeitausgabe ber UART
;
DispTimeUd:
ldi rmp,'T' ; Zeit ausgeben
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,3 ; drei Werte
mov R1,rmp
ldi ZH,HIGH(sTimeD+1) ; Z auf Tage
ldi ZL,LOW(sTimeD+1)
DispTimeUd1:
ld R2,-Z ; Zahl lesen
clr R3
mov R0,R1 ; fhrende Nullen nicht unterdrcken
rcall UartDec2
mov rmp,R1 ; : ausgeben?
cpi rmp,1
breq DispTimeUd2 ; nein
ldi rmp,':'
rcall UartSendChar
DispTimeUd2:
dec R1
brne DispTimeUd1 ; n•hste Zahl
ldi rmp,cCr ; Wagenrcklauf
rcall UartSendChar
ldi rmp,cLf ; Zeilenvorschub
rjmp UartSendChar
;
; Eine Minute ist vergangen, Ausgabe wenn enabled
;
Minute:
cbr rFlg,1<<bMin ; Flagge l•chen
rcall Time ; Systemzeit um eine Minute erh•en
rcall DisplTimeL ; anzeigen
sbrs rFlgD,bUMoni ; Monitor-Flagge auswerten
ret ; nichts weiter zu tun
rcall DispTimeU ; Zeit ber UART ausgeben
rjmp Monitor ; Ergebnisse ber UART ausgeben
;
; Ende von akkucalc
;

http://www.avr-asm-tutorial.net/akkuload/de/akkucalc.asm (2 of 2)1/20/2009 7:50:54 PM


http://www.avr-asm-tutorial.net/akkuload/de/akkukey.asm

; **************************************************************
; * Datei mit Routinen fuer Tastenbedienung des Akkuladers *
; * (C)2005 by Gerhard Schmidt, info@avr-asm-tutorial.net *
; **************************************************************
;
; Routine Register Zweck
; ---------------------------------------------------------
; KeyInit rmp,Z,X Initiiert Tasteneingaben, setzt Startwerte
; Keys rmp Fragt gedrueckte Tasten ab
; fuer die Hauptprogrammschleife
; KeyMenueFirst nn Ausgabe des ersten Tastenmenues
; ---------------------------------------------------------
;
; Konstanten
;
.EQU pLedO = PORTD ; LEDs sind an Port D angeschlossen
.EQU cLedM = 0xF0 ; Alle LED Port Bits gesetzt
.EQU pKeyO = PORTD ; Tasten an Port D angeschlossen
.EQU pKeyD = DDRD ; Tastenrichtungsregister
.EQU pKeyI = PIND ; Tastenlese-Port
.EQU cKeyB = 0xE0 ; Drei Tasten an Bits 7, 6 und 5
.EQU cKeyM = 0x1F ; Maske fuer Loeschen der Bits 7, 6, und 5
;
; ============== Routine zur Initialisierung der Tasten =====
;
; Initiieren der LEDs, LEDs fuer 4 Sekunden einschalten
;
KeyLedInit:
ldi ZH,HIGH(sLedC) ; LED PW-Zaehler Null setzen
ldi ZL,LOW(sLedC)
ldi rmp,5 ; 5 bytes
clr R0
KeyLedInit1:
st Z+,R0
dec rmp
brne KeyLedInit1
in rmp,pLedO
cbr rmp,cLedM ; loeschen des LED-Bits, LED an
out pLedO,rmp
ret
;
; Initiieren der Tasten
;
KeyInit:
clr rKeyLst ; Loesche letzte Taste
clr rKeyRep ; Loesche Zaehler fuer Tastenwiederholung
;
; Loesche die Variablen fuer Tasteneingaben
;
KeyReset:
ldi XH,HIGH(sKeyJ1) ; Ziel im SRAM
ldi XL,LOW(sKeyJ1)
ldi ZH,HIGH(2*KeyInitTable) ; Quellentabelle
ldi ZL,LOW(2*KeyInitTable)
ldi rmp,6 ; 3 Worte, 6 Bytes
KeyReset1:
lpm ; Lese aus Tabelle
adiw ZL,1
st X+,R0 ; in SRAM
dec rmp
brne KeyReset1
clr rmp ; Setze Kanal = 0
sts sKeyCh,rmp
ret
;
; Tabelle fuer Tasteneingabe
;
KeyInitTable:
.DW KeyM1,0,0
;
; ===================== Routinen fuer Hauptschleife ============
;
; bedient die LED-Ausgabe
;
KeyLeds:
in R0,pLedO ; Speichere aktuellen Ausgabestatus
ldi rmp,0x0F ; Loesche alle Ausgabebits, LEDs an
and R0,rmp
lds rmp,sLedC ; lese LED-Zaehler
dec rmp ; zaehle Zaehler herunter
brne KeyLeds4 ; nicht Null, keine Zustandspruefung
lds R1,sState ; Lese Kanalstatus
ldi ZH,HIGH(sLed1) ; Z zeigt auf Kanal
ldi ZL,LOW(sLed1)
ldi XL,4 ; vier Mal wiederholen
KeyLeds1:
lsr R1 ; niedriges Statusbit
brcs KeyLeds2 ; niedrigstes Statusbit ist Eins
ldi XH,32 ; Kanalvergleichswert für 50%-Anzeige
lsr R1 ; hoeheres Statusbit lesen
brcs KeyLeds3 ; Status=10=load, setze Kanalwert
ldi XH,64 ; 00=inactive, spaeter LEDs abschalten
rjmp KeyLeds3 ; setze Kanalwert
KeyLeds2: ; niedriges Statusbit ist Eins
clr XH ; 11=Erhaltungsladung, LED dauernd an
lsr R1 ; hoeheres Bit in Carry
brcs KeyLeds3 ; setze Kanalwert
ldi XH,56 ; 01=Entladen, Led an fuer 8 Zyklen
KeyLeds3: ; speichere Kanalwert und wiederhole
st Z+,XH ; setze Kanalwert
dec XL ; naechster Kanal
brne KeyLeds1 ; weiterer Kanal
ldi rmp,64 ; 64 Zyklen in Zaehler
KeyLeds4: ; vergleiche Kanalwert mit Zaehler
sts sLedC,rmp ; speichere Zaehler
ldi XH,0x80 ; Maske fuer Setzen eines LED-Bit
ldi XL,4 ; vier Kanaele
ldi ZH,HIGH(sLed1) ; Z auf Kanalwert setzen
ldi ZL,LOW(sLed1)
KeyLeds5: ; pruefe ob LED aus sein sollte
ld R1,Z+ ; Lese Kanalwert
cp R1,rmp ; vergleiche Zaehler und Kanalwert
brcs KeyLeds6 ; lasse LED an
or R0,XH ; schalte Kanalausgang an = LED aus
KeyLeds6:
lsr XH ; Maske eine Position rechts
dec XL ; naechster Kanal
brne KeyLeds5 ; noch ein Kanal
out pLedO,R0 ; Setze Ausgabebits
ret ; fertig
;
; Keys fragt die Eingabepins auf gedrueckte Tasten ab
;
Keys:
in R1,pKeyO ; Rette aktuelle Statusbits (LEDs)
in R0,pKeyD ; Sichere Richtungsbits
mov rmp,R0 ; kopiere Richtungsbits
andi rmp,cKeyM ; loesche Richtungsbits
out pKeyD,rmp ; Tastenbits als Eingaenge
mov rmp,R1 ; Pullup-Widerstaende
ori rmp,cKeyB ; Bits auf Eins setzen
out pKeyO,rmp ; an Port
nop ; warte eine Weile
nop
nop
nop
in rmp,pKeyI ; Lese Tastenport
out pKeyD,R0 ; Stelle Richtungsbits wieder her
out pKeyO,R1 ; Stelle Ausgabezustand wieder her
andi rmp,cKeyB ; Isoliere Tastenbits
cpi rmp,cKeyB ; alle Tasten inaktiv?
brne Keys2 ; nein
Keys1:
clr rKeyRep ; Wiederholung auf Null
mov rKeyLst,rmp ; speichern
ret ; fertig
Keys2:
cp rmp,rKeyLst ; gleich letztem Tastenstatus?
brne Keys1 ; nein, loesche Zaehler
inc rKeyRep ; erhoehe Zaehler
ldi rmp,cKeyRep ; vergleiche mit vorgewaehlter Zahl
cp rmp,rKeyRep
breq Keys3 ; gleich, mach weiter
ret
Keys3: ; Taste ok, starte ausgewaehlte Routine
mov R0,rKeyLst ; lese die Tasten erneut
ldi ZH,HIGH(sKeyJ1) ; zeige auf erste Adresse
ldi ZL,LOW(sKeyJ1)
Keys4:
rol R0
brcc Keys5
adiw ZL,2 ; naechste Adresse
rjmp Keys4
Keys5:
ld rmp,Z+ ; Lese Sprungadresse und springe
ld R0,Z
mov R1,R0 ; pruefe ob Adresse Null ist
or R1,rmp
breq Keys6
push rmp
push R0
Keys6:
ret ; jump
;
; ================== Allgemeine Routinen fuer Menues ============
;
; Setze Position auf Menue-Anfang
;
KeyMStrt:
push ZH ; sichere Z
push ZL
ldi ZH,3 ; Zeile 4
ldi ZL,9 ; Position 10
rcall LcdPos ; setze Position
pop ZL ; stelle Z wieder her
pop ZH
ret
;
; loescht den Menueteil und setzt die Position auf den Anfang
;
KeyMClr:
rcall KeyMStrt
ldi rmp,' '
mov R0,rmp
ldi rmp,11
mov R1,rmp
KeyMClr1:
rcall LcdR0
dec R1
brne KeyMClr1
rjmp KeyMStrt
;
; Erstes Menue in Zeile 4 ausgeben
;
KeyMenueFirst:
rcall KeyMStrt ; Setze Position
ldi ZH,HIGH(2*KeyTxtMenue)
ldi ZL,LOW(2*KeyTxtMenue)
rcall LcdDisplZ
ldi rmp,17 ; Setze Cursor Position
sts sLcdCs,rmp
rjmp KeyReset ; initiiere Sprungadresse
; Erstes Menue an LCD
KeyTxtMenue:
.DB " Menue...",0
;
; Fehlermeldung falsche Kanalnummer ausgeben
;
KeyGetChError:
rcall KeyMClr ; Menueteil loeschen
ldi ZH,HIGH(2*KeyTxtChErr) ; Fehlertext
ldi ZL,LOW(2*KeyTxtChErr)
rcall LcdDisplZ ; zeige Text an
ldi rmp,18 ; setze Cursor Position
sts sLcdCs,rmp
ret
;
; Hole Kanalnummer in R0
; Wenn Kanalnummer nicht zwischen 1 und 4 liegt, gib Fehlermeldung
; aus und kehre mit gesetztem Carry zurueck
;
KeyGetChR0:
lds R0,sKeyCh ; Lese aktuellen Kanal
tst R0 ; = Null?
breq KeyGetChR0e
push rmp
ldi rmp,5
cp R0,rmp ; > 4 ?
pop rmp
brcc KeyGetChR0e
clc
ret
KeyGetChR0e:
rcall KeyGetChError
sec
ret
;
KeyTxtChErr:
.DB "Ch error!",0
;
; Setze gewaehlten Kanal auf den Wert n rmp
;
KeyChSet:
rcall KeyGetChR0 ; Kanalnmmer in R0
brcs KeyChSet3
ldi ZL,0xFC ; Kanalmaskenbits = 0
KeyChSet1:
dec R0 ; Kanal erreicht?
breq KeyChSet2 ; ja
sec ; setze Carry fuer Maskenrollen
rol ZL ; naechster Kanal
rol ZL
lsl rmp ; schiebe rmp links
lsl rmp
rjmp KeyChSet1 ; noch mal
KeyChSet2:
lds ZH,sState ; lade Statusbits
and ZH,ZL ; loesche Kanalbits
or ZH,rmp ; setze Kanalbits auf Wert in rmp
sts sState,ZH ; setze neuen Status
KeyChSet3:
ret
;
; Setze PWM-Wert des Kanals auf den Wert in rmp
;
KeySetPwm:
rcall KeyGetChR0
brcs KeySetPwm2
ldi ZH,HIGH(cPwm1S-1) ; loesche PWM-Wert des Kanals
ldi ZL,LOW(cPwm1S-1)
KeySetPwm1:
adiw ZL,1 ; naechster PWM-Kanal
dec R0
brne KeySetPwm1
st Z,rmp ; setze PWM-Wert
KeySetPwm2:
ret
;
; Entlade-Bit des Kanals loeschen
;
KeyClrUnl:
rcall KeyGetChR0
brcs KeyClrUnl2
ldi rmp,0xF7 ; Maske
KeyClrUnl1:
sec ; rolle eine 1 ein
rol rmp ; rotiere Maske links
dec R0 ; naechster Kanal
brne KeyClrUnl1
and rPwmOut,rmp ; loesche Entladebit
KeyClrUnl2:
ret ; fertig
;
; Loesche Kapazitaetszaehler
;
KeyClrCap:
rcall KeyGetChR0
brcs KeyClrCap1
dec R0
ldi ZH,HIGH(sAdcC)
ldi ZL,LOW(sAdcC)
add ZL,R0
add ZL,R0
st Z+,rmp
st Z+,rmp
std Z+6,rmp
KeyClrCap1:
ret
;
; Hole die Parameter des aktuellen Kanals, setze Adresse und hole
; Dezimalzah, erwartet die Parameter-Basisadresse in X und den
; Maximalwert in Z
;
KeyGetParam:
rcall KeyGetChR0
brcs KeyGetParam1
dec R0
lsl R0 ; * 8
lsl R0
lsl R0
add XL,R0 ; korrigiere Adresse
clr R0
adc XH,R0
ld R0,X+ ; lese LSB
sts sKeyNW,R0 ; speichere Dezimalzahl
ld R0,X ; lese MSB
sts sKeyNW+1,R0
sts sKeyNM,ZL
sts sKeyNM+1,ZH
KeyGetParam1:
ret
;
; Setze die Parameter im aktuellen Kanal
; Erwartet Parameter-Basisadresse in X und Text in Z
;
KeySetParam:
rcall KeyGetChR0
brcs KeySetParam1
dec R0
lsl R0 ; * 8
lsl R0
lsl R0
add XL,R0 ; korrigiere Adresse
clr R0
adc XH,R0
lds rmp,sKeyNW
st X+,rmp
lds rmp,sKeyNW+1
st X,rmp
rcall KeyMClr
rcall LcdDisplZ
ldi ZH,HIGH(KeyM12a)
ldi ZL,LOW(KeyM12a)
ijmp
KeySetParam1:
ret
;
; Nach Beenden eines Menueeintrags zeige Text in X an
;
KeyMDone:
rcall KeyMClr ; Loesche Menuebereich der LCD
rcall LcdDisplZ
mov ZH,XH
mov ZL,XL
ijmp
;
; ================= Behandlung von Menueeintraegen ===========
;
; Ausgabe des Menueeintrags in X, des Menueeintrags in sKeyNC
;
KeyMOut:
rcall KeyMClr
KeyMOut1:
mov ZH,XH ; kopiere Menuebeginn nach Z
mov ZL,XL
lds R1,sKeyNC ; lese Menueeintragnummer
KeyMOut2: ; pruefe ob der Menueeintrag erreicht ist
tst R1 ; Menueeintraszaehler = 0?
brne KeyMOut5 ; nicht erreicht, weiter
KeyMOut3: ; Menueeintrag erreicht, Ausgabe des Menuetexts
lpm
adiw ZL,1
mov rmp,R0
cpi rmp,'#' ; Endezeichen
breq KeyMOut4
rcall LcdChar
rjmp KeyMout3
KeyMOut4: ; Ausgabe beendet, suche NULL
lpm
adiw ZL,1
tst R0
brne KeyMOut4
; Lese die LCD Cursor position und die Sprungadresse
lpm
adiw ZL,1
sts sLcdCs,R0
lpm
adiw ZL,1
sts sKeyJ3,R0 ; speichere in Adresse fuer Taste 3
lpm
sts sKeyJ3+1,R0
ret
KeyMOut5: ; nicht der gewueschte Eintrag suche naechsten Text
lpm
adiw ZL,1
tst R0
brne KeyMOut5
adiw ZL,3
lpm
ldi rmp,0xFF
cp rmp,R0
breq KeyMOut6
dec R1
rjmp KeyMOut2
KeyMOut6: ; starte neu
clr R1
sts sKeyNC,R1
rjmp KeyMOut1
;
; ================= Hole Dezimalzahl Eingabe ============
;
;
; Zeigt die Dezimalzal in sKeyNW am Ende von Zeile 4 der LCD an
;
KeyDecDispl: ; zeige Dezimalzahl an
ldi ZH,3 ; Zeile 4
ldi ZL,15 ; Position 16
rcall LcdPos ; Setze LCD Position
lds R2,sKeyNW ; lese Dezimalzahl
lds R3,sKeyNW+1
rcall LcdDec5 ; schreibe Zahl auf LCD
lds ZL,sKeyNC ; setze LCD Cursor Position
subi ZL,-15
sts sLcdCs,ZL
ldi ZH,3
rjmp LcdPos
;
; Setze die Sprungadresse fuer die Dezimaleingabe und hole Zahl
; erwartet: Textzeiger in Z, Rueckadresse in X, Abbruchadresse
; in sKeyJ1
;
KeyDec:
rcall KeyMClr ; loesche Menuebereich
rcall LcdDisplZ ; Textausgabe
ldi ZH,HIGH(sKeyJR) ; auf Ruecksprungadresse zeigen
ldi ZL,LOW(sKeyJR)
st Z+,XL
st Z+,XH
lds XL,sKeyJ1 ; speichere Ruecksprungsadresse
lds XH,sKeyJ1+1
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecL) ; Taste 1 Adresse
ldi XH,HIGH(KeyDecL)
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecU) ; Taste 2 Adresse
ldi XH,HIGH(KeyDecU)
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecR) ; Taste 3 Adresse
ldi XH,HIGH(KeyDecR)
st Z+,XL
st Z+,XH
ldi rmp,4 ; Cursor auf letzte Ziffer
sts sKeyNC,rmp
rjmp KeyDecDispl ; Zeige Zahl an und setze Cursor
;
KeyDecL: ; Linke Taste
lds rmp,sKeyNC ; Cursor Position eins links
dec rmp
cpi rmp,0xFF ; ueber Anfang hinaus?
breq KeyDecL1
sts sKeyNC,rmp ; setze Cursor
rjmp KeyDecDispl ; Zahlanzeige und Cursor setzen
KeyDecL1:
lds ZL,sKeyJS ; lese Abbruchadresse
lds ZH,sKeyJS+1
ijmp ; springe zur Abbruchroutine
;
KeyDecU: ; Mittlere Taste
ldi ZH,HIGH(2*KeyDecTbl) ; Z auf Dezimaltabelle
ldi ZL,LOW(2*KeyDecTbl)
lds rmp,sKeyNC ; plus aktuelle Position
lsl rmp ; * 2
add ZL,rmp ; zeige auf Wert in Dezimaltabelle
clr rmp
adc ZH,rmp
lpm ; lese Dezimalwert
mov XL,R0
adiw ZL,1
lpm
mov XH,R0
lds ZL,sKeyNW ; lese aktuelle Dezimalzahl
lds ZH,sKeyNW+1
add ZL,XL ; Addiere beide
adc ZH,XH
lds XL,sKeyNM ; lese Maximalzahl
lds XH,sKeyNM+1
sec
cpc ZL,XL ; vergleiche mit Maximum
cpc ZH,XH
brcs KeyDecU1
clr ZH ; > Max., loesche Zahl
clr ZL
KeyDecU1:
sts sKeyNW,ZL ; speichere Zahl
sts sKeyNW+1,ZH
rjmp KeyDecDispl ; zeige Dezimalzahl an, setze Cursor
;
KeyDecR: ; Rechte Taste
lds rmp,sKeyNC ; lese Cursor
inc rmp ; naechste Position
cpi rmp,5 ; rechts raus?
brcc KeyDecR1 ; ja
sts sKeyNC,rmp ; speichere Position
rjmp KeyDecDispl
KeyDecR1:
lds ZL,sKeyJR ; lese Sprungadresse
lds ZH,sKeyJR+1
ijmp ; springe zum Beenden der Eingabe
;
KeyDecTbl: ; Dezimaltabelle
.DW 10000
.DW 1000
.DW 100
.DW 10
.DW 1
;
; ================= Menues =====================
;
; Menue 1, Auswahl
;
KeyM1:
ldi XH,HIGH(2*KeyTxtM1) ; Menuetext
ldi XL,LOW(2*KeyTxtM1)
rcall KeyMOut ; zeige Menuetext an
KeyM1a:
ldi rmp,LOW(KeyMenueFirst) ; Setze linke Sprungadresse
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyMenueFirst)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM1Up) ; Setze mittlere Sprungadresse
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM1Up)
sts sKeyJ2+1,rmp
clr rmp ; beginne mit Menueeintrag 0
sts sKeyNC,rmp
ret
;
; Menue 1 Erhoehen Routine
;
KeyM1Up:
lds rmp,sKeyNC ; naechst hoeherer Menueeintrag
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM1) ; zeige mit X auf Menuetabelle
ldi XL,LOW(2*KeyTxtM1)
rjmp KeyMOut
;
; Menue 11: Auswahl von Akku-Id und Kanal
;
KeyM11:
clr rmp ; Setze ausgewaehlten Menueeintrag auf 0
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM11) ; Zeiger X auf Menuetabelle
ldi XL,LOW(2*KeyTxtM11)
rcall KeyMOut ; Zeige Menueeintrag an
KeyM11a:
ldi rmp,LOW(KeyM1) ; Setze Sprungadresse fuer linke Taste auf Menue 1
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM11Up) ; Setze mittlere Sprungadresse auf M11Up
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM11Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 11 Up Tastenroutine
;
KeyM11Up:
lds rmp,sKeyNC ; naechster Menueeintrag
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM11) ; ausgewaehlter Menuetext
ldi XL,LOW(2*KeyTxtM11)
rjmp KeyMOut ; Ausgabe des Menueeintrags
;
; Tastenauswahl-Routinen
;
KeyM111: ; Waehle Akku-Id
rcall KeyGetChR0 ; lese Kanal
brcs KeyM111e
dec R0
ldi ZH,HIGH(sAdcAI1) ; lese Akku-Id
ldi ZL,LOW(sAdcAI1)
add ZL,R0
add ZL,R0
ld rmp,Z
sts sKeyNW,rmp
clr rmp
sts sKeyNW+1,rmp
lds rmp,sEANm ; lese Anzahl der Id's
sts sKeyNM,rmp ; setze Maximaleingabe
clr rmp
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM111R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM111R)
ldi ZH,HIGH(2*KeyTxtM111) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM111)
rjmp KeyDec ; hole Dezimalzahl
KeyM111e:
ret
;
KeyTxtM111:
.DB "Akku=",0
;
; Rueckkehr von der Dezimalahleingabe mit Akku-Id
;
KeyM111R:
rcall KeyGetChR0
brcs KeyM111Re
dec R0
ldi ZH,HIGH(sAdcAI1)
ldi ZL,LOW(sAdcAI1)
add ZL,R0
add ZL,R0
lds rmp,sKeyNW ; kopiere Dezimalzahl in Kanal
st Z,rmp
rcall IdSetPar ; Setze Parameter
ldi XH,HIGH(KeyM11a) ; Sprung zurueck
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt112R)
ldi ZL,LOW(2*KeyTxt112R)
rjmp KeyMDone
KeyM111Re:
ret
;
KeyTxt111R:
.DB "Akku-Id ok",0,0
;
KeyM112: ; Waehle Kanalnummer aus
lds rmp,sKeyCh ; lese Kanal, kopiere nach Dezimalzahleingabe
sts sKeyNW,rmp
clr rmp
sts sKeyNW+1,rmp
ldi rmp,4 ; Setze Maximumwert
sts sKeyNM,rmp
clr rmp
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM112R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM112R)
ldi ZH,HIGH(2*KeyTxtM112) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM112)
rjmp KeyDec ; hole Dezimalzahl
;
KeyTxtM112:
.DB "Kanal=",0,0
;
; Setze Kanal auf Eingabezahl
;
KeyM112R:
lds rmp,sKeyNW ; kopiere Eingabezahl in Kanal
sts sKeyCh,rmp
ldi XH,HIGH(KeyM11a) ; springe zurueck
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt112R)
ldi ZL,LOW(2*KeyTxt112R)
rjmp KeyMDone
;
KeyTxt112R:
.DB "Kanal ok",0,0
;
KeyM113: ; Direkt laden
ldi rmp,LOW(500)
sts sKeyNW,rmp
ldi rmp,HIGH(500)
sts sKeyNW+1,rmp
ldi rmp,LOW(9999)
sts sKeyNM,rmp
ldi rmp,HIGH(9999)
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM113R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM113R)
ldi ZH,HIGH(2*KeyTxtM113) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM113)
rjmp KeyDec ; hole Dezimalzahl
;
KeyTxtM113:
.DB "Kapaz.=",0
;
KeyM113R:
rcall KeyGetChR0
brcs KeyM113Re
rcall KeyClrUnl
ldi rmp,0x02 ; setze Ladestatus
rcall KeyChSet
ldi rmp,128
rcall KeySetPwm
rcall KeyGetChR0
dec R0
lsl R0
lsl R0
lsl R0
ldi ZH,HIGH(sCh1LC) ; zeige auf Ladestrom
ldi ZL,LOW(sCh1LC)
add ZL,R0
clr R0
adc ZH,R0
lds XL,sKeyNW ; lese Kapazitaet
lds XH,sKeyNW+1
mov R2,XL ; kopiere
mov R3,XH
lsr R3 ; / 2
ror R2
lsr R3 ; / 4
ror R2
lsr R3 ; / 8
ror R2
st Z+,R2 ; setze Ladestrom
st Z+,R3
add XL,R2 ; addiere zur Nennkapazitaet
adc XH,R3
st Z+,XL ; setze Kapazitaet
st Z+,XH
lsl XL ; * 2
rol XH
clr rmp
rol rmp
st Z+,XH ; setze den Erhaltungsstrom
st Z,rmp
ldi XH,HIGH(KeyM11a) ; Ruecksprungadresse
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt113D) ; Textausgabe
ldi ZL,LOW(2*KeyTxt113D)
rjmp KeyMDone
KeyM113Re:
ret
;
KeyTxt113D:
.DB "Autoladen",0
;
; Menue "Setze" Routinen
;
KeyM12:
clr rmp ; Setze gewaehlten Menueeintrag auf 0
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM12) ; X zeigt auf Menuetabelle
ldi XL,LOW(2*KeyTxtM12)
rcall KeyMOut ; Zeige Menueeintrag an
KeyM12a:
ldi rmp,LOW(KeyM1) ; Setze linke Sprungadresse auf Menue 1
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM12Up) ; Setze mittlere Sprungadresse auf M12Up
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM12Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 12 Up Tastenroutine
;
KeyM12Up:
lds rmp,sKeyNC ; naechster Menueeintrag
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM12) ; gewaehlter Menuetext
ldi XL,LOW(2*KeyTxtM12)
rjmp KeyMOut ; gib Menueeintrag aus
;
KeyM121:
ldi XH,HIGH(sCh1UV) ; Kanalnummer auf Entladespannung
ldi XL,LOW(sCh1UV)
ldi ZH,HIGH(1300) ; Maximalwert setzen
ldi ZL,LOW(1300)
rcall KeyGetParam ; Parameter in X auf Eingabe und Maximum auf Z
ldi XH,HIGH(KeyM121R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM121R)
ldi ZH,HIGH(2*KeyTxtM121) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM121)
rjmp KeyDec; hole Dezimalzahl
;
KeyM122:
ldi XH,HIGH(sCh1LC) ; Kanalnummer auf Ladestrom
ldi XL,LOW(sCh1LC)
ldi ZH,HIGH(350) ; Maximalwert
ldi ZL,LOW(350)
rcall KeyGetParam ; Parameter in X auf Eingabe und Maximum auf Z
ldi XH,HIGH(KeyM122R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM122R)
ldi ZH,HIGH(2*KeyTxtM122) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM122)
rjmp KeyDec; Hole Dezimalzahl
;
KeyM123:
ldi XH,HIGH(sCh1LW) ; Kanalnummer auf Ladekapazitaet
ldi XL,LOW(sCh1LW)
ldi ZH,HIGH(9999) ; Maximawert
ldi ZL,LOW(9999)
rcall KeyGetParam ; Parameter in X auf Eingabe und Maximum auf Z
ldi XH,HIGH(KeyM123R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM123R)
ldi ZH,HIGH(2*KeyTxtM123) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM123)
rjmp KeyDec; hole Dezimalzahl
;
KeyM124:
ldi XH,HIGH(sCh1MC) ; Kanalnummer auf Erhaltungsstrom
ldi XL,LOW(sCh1MC)
ldi ZH,HIGH(100) ; Maximalwert
ldi ZL,LOW(100)
rcall KeyGetParam ; Parameter in X auf Eingabe und Maximum af Z
ldi XH,HIGH(KeyM124R) ; Ruecksprungadresse in X
ldi XL,LOW(KeyM124R)
ldi ZH,HIGH(2*KeyTxtM124) ; Textadresse in Z
ldi ZL,LOW(2*KeyTxtM124)
rjmp KeyDec; Hole Dezimalzahl
;
KeyTxtM121:
.DB "Entlade=",0,0
;
KeyTxtM122:
.DB "Laden I=",0,0
;
KeyTxtM123:
.DB "Kapaz.=",0
;
KeyTxtM124:
.DB "Erhalt.=",0,0
;
; Setze die Entladespannung auf den Wert sKeyNW
;
KeyM121R:
ldi XH,HIGH(sCh1UV) ; X auf Entladespannung
ldi XL,LOW(sCh1UV)
ldi ZH,HIGH(2*KeyTxtM121D) ; Z auf Text
ldi ZL,LOW(2*KeyTxtM121D)
rjmp KeySetParam ; setze Parameter
;
; Setze den Ladestrom auf den Wert in sKeyNW

http://www.avr-asm-tutorial.net/akkuload/de/akkukey.asm (1 of 2)1/20/2009 7:50:57 PM


http://www.avr-asm-tutorial.net/akkuload/de/akkukey.asm

;
KeyM122R:
ldi XH,HIGH(sCh1LC) ; X auf Ladestrom
ldi XL,LOW(sCh1LC)
ldi ZH,HIGH(2*KeyTxtM122D) ; Z auf Text
ldi ZL,LOW(2*KeyTxtM122D)
rjmp KeySetParam ; setze Parameter
;
; Setze die Nennkapazitaet auf den Wert in sKeyNW
;
KeyM123R:
ldi XH,HIGH(sCh1LW) ; X auf Kapazitaet
ldi XL,LOW(sCh1LW)
ldi ZH,HIGH(2*KeyTxtM123D) ; Z auf Text
ldi ZL,LOW(2*KeyTxtM123D)
rjmp KeySetParam ; setze Parameter
;
; Setze den Erhaltungsstrom auf den Wert in sKeyNW
;
KeyM124R:
ldi XH,HIGH(sCh1MC) ; X auf Erhaltungsstrom
ldi XL,LOW(sCh1MC)
ldi ZH,HIGH(2*KeyTxtM124D) ; Z auf Text
ldi ZL,LOW(2*KeyTxtM124D)
rjmp KeySetParam ; setze Parameter
;
KeyTxtM121D:
.DB "Entladen ok",0
;
KeyTxtM122D:
.DB "Laden ok",0,0
;
KeyTxtM123D:
.DB "Kapaz. ok",0
;
KeyTxtM124D:
.DB "Erhalt. ok",0,0
;
;
; Menueeintraege Befehl ausfuehren
;
KeyM13:
clr rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM13) ; Menuetext
ldi XL,LOW(2*KeyTxtM13)
rcall KeyMOut ; Zeige Menue an
KeyM13a:
ldi rmp,LOW(KeyM1) ; Setze linke Sprungadresse
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM13Up) ; Setze mittlere Sprungadresse
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM13Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 13 Up Tastenroutine
;
KeyM13Up:
lds rmp,sKeyNC
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM13) ; Menuetext
ldi XL,LOW(2*KeyTxtM13)
rjmp KeyMOut
;
; Befehls-Menues, setzt Status auf Wert in sKeyCh
;
KeyM131: ; setze sState auf Entladen
ldi rmp,0x01
rcall KeyChSet
clr rmp
rcall KeySetPwm
rcall KeyClrCap
ldi rmp,0x08 ; setze sState auf Entladen
lds R0,sKeyCh
KeyM131b:
lsl rmp
dec R0
brne KeyM131b
or rPwmOut,rmp ; setze Entladebit des PWM-Kanals
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM131D)
ldi ZL,LOW(2*KeyTxtM131D)
rjmp KeyMDone
;
KeyM132: ; setze sState auf Laden
ldi rmp,0x01
rcall KeyChSet
rcall KeyClrUnl ; loesche Entladebit
rcall KeyClrCap
ldi rmp,128 ; setze PWM auf 1100 mV
rcall KeySetPwm
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM132D)
ldi ZL,LOW(2*KeyTxtM132D)
rjmp KeyMDone
;
KeyM133: ; setze sState auf Erhaltungsladung
ldi rmp,0x01
rcall KeyChSet
rcall KeyClrUnl ; loesche Entladebit
ldi rmp,128 ; setze die PWM auf 1100 mV
rcall KeySetPwm
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM133D)
ldi ZL,LOW(2*KeyTxtM133D)
rjmp KeyMDone
;
KeyM134: ; loesche sState (Kanal aus)
clr rmp
rcall KeyChSet
rcall KeyClrUnl ; loesche Entladebit
clr rmp ; PWM auf Null
rcall KeySetPwm
rcall KeyClrCap ; Kapazitaet loeschen
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM134D)
ldi ZL,LOW(2*KeyTxtM134D)
rjmp KeyMDone
;
KeyTxtM131D:
.DB "Entladen",0,0
KeyTxtM132D:
.DB "Laden",0
KeyTxtM133D:
.DB "Erhalten",0,0
KeyTxtM134D:
.DB "Aus",0
;
; =================== Menuetabellen ===================
;
; Menue 1
;
KeyTxtM1:
.DB "Auswahl...# ",0,19
.DW KeyM11
.DB "Setze...# ",0,17
.DW KeyM12
.DB "Befehl...#",0,18
.DW KeyM13
.DW 0xFFFF
;
KeyTxtM11:
.DB "Akku-Id...# ",0,19
.DW KeyM111
.DB "Kanal...# ",0,17
.DW KeyM112
.DB "Direktlade# ",0,19
.DW KeyM113
.DW 0xFFFF
;
KeyTxtM12:
.DB "Entlade...# ",0,19
.DW KeyM121
.DB "Laden...# ",0,16
.DW KeyM122
.DB "Kapazit...# ",0,19
.DW KeyM123
.DB "Erhaltg...# ",0,19
.DW KeyM124
.DW 0xFFFF
;
KeyTxtM13:
.DB "Entlade...# ",0,19
.DW KeyM131
.DB "Lade...#",0,16
.DW KeyM132
.DB "Erhaltg...# ",0,19
.DW KeyM133
.DB "Aus...# ",0,15
.DW KeyM134
.DW 0xFFFF
;

http://www.avr-asm-tutorial.net/akkuload/de/akkukey.asm (2 of 2)1/20/2009 7:50:57 PM


http://www.avr-asm-tutorial.net/akkuload/de/akkulcd.asm

; **************************************************************
; * Include-Datei fuer LCD-Routinen Akkuload, Version 0.1 02/05*
; * (C)2005 by Gerhard Schmidt, info@avr-asm-tutorial.net *
; **************************************************************
;
; --------------------------------------------------------------
; Routine Register Funktion
; --------------------------------------------------------------
; LcdInit rmp,R0,Z Initiiert das LCD-Display zu Beginn auf:
; 8-Bit-Interface, 4 Zeilen, kein Shift,
; aktiver Cursor und blinkend
; LcdR0 rmp gibt das Zeichen in R0 auf der aktuellen
; Position des LCD aus, R0 bleibt erhalten
; LcdChar rmp,R0 gibt das Zeichen in rmp auf der aktuellen
; Position des LCD aus, rmp wird geaendert,
; Zeichen bleibt in R0 erhalten
; LcdDisplZ rmp,R0,Z gibt den Text im Flash ab Z auf der LCD
; aus, stoppt beim NULL-Zeichen
; LcdLine rmp setzt die Ausgabe der LCD auf die Zeile
; in rmp, erwartet 0..3 in rmp fuer die
; Zeilen 1..4
; LcdLineCl rmp,R0,Z loescht die Zeile des LCD, auf die rmp
; zeigt, durch Schreiben von Leerzeichen
; LcdPos rmp,Z setzt die LCD auf die Position in Z,
; ZH ist die Zeile, ZL ist die Position in
; dieser Zeile (0..19)
; LcdMClr rmp loescht den Menueteil und setzt die
; Position in dieser Zeile auf den Anfang
; LcdMStrt rmp,R0,Z Setzt die LCD Cursor Position auf den
; Menueanfang
; LcdCursor rmp,Z Setzt den LCD-Cursor auf seine korrekte
; Position nach Ausgaben,Position<8: zeigt
; Menueausgabe 1 an
; LcdHex2 rmp Schreibt den Inhalt von rmp in Hex an die
; aktuelle LCD-Position (debug)
; LcdDec5 rmp,R0,Z schreibt die Binaerzahl in R3:R2 als
; LcdDec4 Dezimalzahl an die aktuelle LCD-Position,
; LcdDec3 5, 4, 3 oder 2 Ziffern werden angezeigt
; LcdDec2
; --------------------------------------------------------------
;
; Konstanten
;
.EQU pLcdCO = PORTD
.EQU pLcdCD = DDRD
.EQU pLcdCI = PIND
.EQU pLcdDO = PORTB
.EQU pLcdDD = DDRB
.EQU pLcdDI = PINB
.EQU bLcdE = 2 ; E-Eingang des Displays
.EQU bLcdRw = 3 ; Read/Write Kontrolle des Display
.EQU bLcdRs = 4 ; Register Select des Display
;
; Verzoegerungsroutinen fuer die Display-Initiierung
; Anzahl der Takte einschlieszlich rcall: 3+7+4*Z-4+7 = 4*Z+13
; Verzoegerung in Mikrosekunden: (4*Z+13)/8
; Berechnung von Z = (8*t[µs]-13)/4
;
; Verzoegerung 15 ms
;
.EQU cLcdWt15000 = (8*15000-13)/4 ; = 29996
LcdWt15000:
ldi ZH,HIGH(cLcdWt15000) ; 1
ldi ZL,LOW(cLcdWt15000) ; 2
rjmp LcdWt ; 4
;
; Verzoegerung 4,1 ms
;
.EQU cLcdWt4100 = (8*4100-13)/4 ; = 8196
LcdWt4100:
ldi ZH,HIGH(cLcdWt4100) ; 1
ldi ZL,LOW(cLcdWt4100)
rjmp LcdWt
;
; Verzoegerung 4,5 ms
;
.EQU cLcdWt4500 = (4500*8-13)/4
LcdWt4500:
ldi ZH,HIGH(cLcdWt4500) ; 1
ldi ZL,LOW(cLcdWt4500) ; 2
rjmp LcdWt ; 4
;
; Verzoegerung 1,64 ms
;
.EQU cLcdWt1640 = (1640*8-13)/4 ; = 3276
LcdWt1640:
ldi ZH,HIGH(cLcdWt1640) ; 1
ldi ZL,LOW(cLcdWt1640) ; 2
rjmp LcdWt ; 4
;
; Verzegerung 100 µs
;
.EQU cLcdWt100 = (100*8-13)/4
LcdWt100:
ldi ZH,HIGH(cLcdWt100)
ldi ZL,LOW(cLcdWt100)
rjmp LcdWt
;
; Verzoegerung 40 µs
;
.EQU cLcdWt40 = (40*8-13)/4 ; = 76
LcdWt40:
ldi ZH,HIGH(cLcdWt40) ; 1
ldi ZL,LOW(cLcdWt40) ; 2
nop ; 3
nop ; 4
;
; Wartet auf Z Verzoegerung
; Anzahl Takte einschlieszlich ret = 4*(Z-1)+7
; Verzoegerung in µs bei 8 MHz: (4*(Z-1)+7)/8
;
LcdWt:
sbiw ZL,1 ; 2
brne LcdWt ; 2/1
ret ; 4
;
; Verzoegerung fuer einen aktiven E-Puls ist 1 µs
;
LcdDel1:
nop
ret
;
; Aktiviere E fuer 1 µs
;
LcdE:
sbi pLcdCO,bLcdE ; setze E aktiv
rcall LcdDel1 ; 1 µs Verzoegerung
cbi pLcdCO,bLcdE ; loesche E
ret
;
; Pruefe ob die LCD busy ist nach Ausgabe eines Zeichens
; stellt zu Beginn fest, ob die LCD angeschlossen ist
;
LcdChck:
cbi pLcdCO,bLcdRw ; Schreibe Daten an LCD
sbi pLcdCO,bLcdRs ; setze RS-Eingang aktiv
clr rmp ; alle Datenbits auf Eingang
out pLcdDD,rmp
ser rmp ; Pullup-Widerstaende einschalten
out pLcdDO,rmp
cbi pLcdCO,bLcdRs ; loesche Rs
sbi pLcdCO,bLcdRw ; setze RW
sbi pLcdCO,bLcdE ; activiere E
in rmp,pLcdDI ; lese Display
tst rmp ; springe wenn Adresse und Busy nicht Null sind
sbr rFlg,1<<bLcdOk ; setze die LCD-ok-Flagge
cbi pLcdCO,bLcdE ; loesche E
cbi pLcdCO,bLcdRw ; loesche RW
ret
;
; Funktionseinstellung der LCD zu Beginn
;
LcdInitFunct:
cbi pLcdCO,bLcdRs ; loesche RS
cbi pLcdCO,bLcdRw ; loesche RW
ldi rmp,0x38 ; Setze 8 bit interface, 2 Zeilen
out pLcdDO,rmp ; an Datenausgang
rcall LcdE
rcall LcdWt4100 ; warte 4100 µs
rcall LcdE
rcall LcdWt100 ; warte 100 µs
rcall LcdE
rcall LcdWt100 ; warte 100 µs
ldi rmp,0x08 ; Display aus
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; warte 40 µs
ldi rmp,0x01 ; loesche Display
out pLcdDO,rmp
rcall LcdE
rcall LcdWt4500 ; warte 4,5 ms
ldi rmp,0x06 ; Eingabemodus, erhoehen, keine Shift
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40
ldi rmp,0x10 ; Display Cursor Shift
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; warte 40 µs
ldi rmp,0x02 ; Display/Cursor Home
out pLcdDO,rmp
rcall LcdE
rcall LcdWt1640 ; warte fuer 1,64 ms
ldi rmp,0x0F ; Display aktiv, Cursor an, blinkend
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; warte 40 µs
rjmp LcdChck ; pruefe die LCD
;
; Warte bis die LCD nicht mehr busy ist
;
LcdBusy:
clr rmp ; Setze Datenport auf Eingang
out pLcdDD,rmp
cbi pLcdCO,bLcdRs ; Loesche RS
sbi pLcdCO,bLcdRw ; Setze Display auf Lesen
sbi pLcdCO,bLcdE ; Enable LCD
LcdBusy1:
nop ; warte ein bisschen
nop ; noch ein bisschen
sbic pLcdDI,7 ; springe wenn busy-Bit Null ist
rjmp LcdBusy1 ; warte weiter
cbi pLcdCO,bLcdE ; Loesche E
ret
;
; Sende Kontrollanweisng in rmp an LCD
;
LcdCtrl:
push rmp ; sichere rmp
rcall LcdBusy ; warte auf nicht mehr busy
ldi rmp,0xFF ; Setze Datenport auf Ausgang
out pLcdDD,rmp
pop rmp
out pLcdDO,rmp ; Daten an Port
cbi pLcdCO,bLcdRs ; loesche RS
cbi pLcdCO,bLcdRw ; loesche R/W
rcall LcdE ; aktiviere E fuer 1 µs
clr rmp ; Datenport aus
out pLcdDD,rmp
ret
;
; Schreibe Zeichen in rmp an LCD
;
LcdChar:
mov R0,rmp ; kopiere Zeichen in R0
;
; Schreibe Zeichen in R0 an LCD
;
LcdR0:
rcall LcdBusy
ldi rmp,0xFF ; Datenausgaberichtung
out pLcdDD,rmp
out pLcdDO,R0 ; Zeichen auf Ausgabeport
sbi pLcdCO,bLcdRs ; Setze RS
cbi pLcdCO,bLcdRw ; Loesche R/W
rcall LcdE ; aktiviere E fuer 1 µs
clr rmp ; deaktiviere Datenport
out pLcdDD,rmp
ret
;
; Schreibe Text im Flash ab Z auf Display
;
LcdDisplZ:
lpm ; lese ein Zeichen aus Flash
adiw ZL,1
tst R0 ; NULL-Zeichen?
breq LcdDisplZ1
rcall LcdR0 ; Zeichen an Display
rjmp LcdDisplZ
LcdDisplZ1:
ret
;
; Initiiere die LCD
;
LcdInit:
ser rmp ; Setze Datenport alle als Ausgang
out pLcdDD,rmp
cbi pLcdCO,bLcdE ; Bit E auf Null
sbi pLcdCD,bLcdE ; Richtungsbit E als Ausgang
cbi pLCDCO,bLcdRw ; Bit R/W auf Null
sbi pLcdCD,bLcdRw ; Richtungsbit R/W als Ausgang
cbi pLcdCO,bLcdRs ; Bit RS auf Null
sbi pLcdCD,bLcdRs ; Richtungsbit RS als Ausgang
rcall LcdWt15000 ; Warten fuer 15 ms
rcall LcdInitFunct ; Setze 8-bit interface und Anzahl Zeilen
rcall LcdChck ; pruefe die LCD
sbrs rFlg,bLcdOk ; springe wenn LCD ok
ret
clr rmp ; setze LCD auf Zeile 1
rcall LcdLine
ldi ZH,HIGH(2*LcdTxtInit1) ; Z auf Text
ldi ZL,LOW(2*LcdTxtInit1)
rcall LcdDisplZ ; schreibe Text auf LCD
ldi rmp,1 ; setze LCD-Zeile 2
rcall LcdLine
rcall LcdDisplZ
ldi rmp,2 ; setze LCD-Zeile 3
rcall LcdLine
rcall LcdDisplZ
ldi rmp,3 ; setze LCD-Zeile 4
rcall LcdLine
rjmp LcdDisplZ
;
; LcdLine setzt den Eingabecursor in die ausgewahlte Zeile in rmp
;
LcdLine:
cpi rmp,1 ; rmp = 0 oder 1
brcs LcdLine1 ; rmp=0, setzt Zeile 1
breq LcdLine2 ; rmp=1, setzt Zeile 2
cpi rmp,2
breq LcdLine3 ; rmp=2, setzt Zeile 3
ldi rmp,0x54 ; rmp>2, setzt Zeile 4
rjmp LcdLine4
LcdLine1:
clr rmp ; Zeile 1 startet bei 0
rjmp LcdLine4
LcdLine2:
ldi rmp,0x40 ; Zeile 2 startet bei 0x40
rjmp LcdLine4
LcdLine3:
ldi rmp,20 ; Zeile 3 startet bei 20
LcdLine4:
sbr rmp,0x80 ; setze Kontrollbit
rjmp LcdCtrl
;
; LCD loesche Zeile
;
LcdLineCl:
mov ZH,rmp ; sichere Zeilennummer
rcall LcdLine ; setze Zeile
ldi rmp,' ' ; Leerzeichen
mov R0,rmp ; nach R0
ldi ZL,20 ; ZL ist Zaehler
LcdLineCl1:
rcall LcdR0 ; schreibe Zeichen in R0
dec ZL ; naechstes
brne LcdLineCl1 ; noch mal
mov rmp,ZH ; stelle rmp wieder her
rjmp LcdLine
;
; LcdPos setzt die LCD auf die Position in Z
;
LcdPos:
cpi ZH,1 ; Zeile = 0 oder 1
brcs LcdPos1 ; ZH=0, setzt Zeile 1
breq LcdPos2 ; ZH=1, setzt Zeile 2
cpi ZH,2
breq LcdPos3 ; ZH=2, setzt Zeile 3
ldi rmp,0x54 ; ZH>2, setzt Zeile 4
rjmp LcdPos4
LcdPos1:
clr rmp ; Zeile 1 startet bei 0
rjmp LcdPos4
LcdPos2:
ldi rmp,0x40 ; Zeile 2 startet bei 0x40
rjmp LcdPos4
LcdPos3:
ldi rmp,20 ; Zeile 3 startet bei 20
LcdPos4:
add rmp,ZL ; addiere Position in Zeile
sbr rmp,0x80
rjmp LcdCtrl
;
; Setzt die LCD Cursor Position
;
LcdCursor:
sbrs rFlg,bLcdOk ; LCD ok?
ret
lds rmp,sLcdCs ; lese Cursor-Position
cpi rmp,8 ; mindest-Position
brcc LcdCursor1
rcall KeyMenueFirst ; Zeige Menue in Zeile an
LcdCursor1:
ldi ZH,3 ; Zeile 4
lds ZL,sLcdCs ; Lese erneut Position
rjmp LcdPos
;
; LCDHEX2 schreibt den Inhalt von rmp in Hex (debug)
;
LcdHex2:
push rmp
swap rmp
rcall LcdHexN
pop rmp
LcdHexN:
andi rmp,0x0F
cpi rmp,0x0A
brcs LcdHexN1
subi rmp,-7
LcdHexN1:
subi rmp,-'0'
rcall LcdChar
ret
;
; LcdDecDigit zieht die Dezimalzahl ab und schreibt eine Ziffer
;
LcdDecDigit:
clr rmp ; zaehlt waehrend der Subtraktion
LcdDecDigit1:
cp R2,ZL ; vergleiche LSB
cpc R3,ZH ; dto., MSB
brcs LcdDecDigit2 ; Subtraktion beendet
sub R2,ZL ; subtrahiere LSB
sbc R3,ZH ; dto., MSB
inc rmp ; erhoehe Anzahl der Subtraktionen
rjmp LcdDecDigit1 ; weiter
LcdDecDigit2:
tst rmp ; null mal?
brne LcdDecDigit3 ; nein
tst R0 ; pruefe of fuehrende Nullen aktiv
brne LcdDecDigit3
ldi rmp,' ' ; fuehrende Null loeschen
rcall LcdChar ; Leerzeichen ausgeben
clr R0
ret
LcdDecDigit3:
subi rmp,-'0' ; addiere ASCII-Null
rcall LcdChar ; stelle Ziffer im LCD dar
clr R0 ; keine fuehrende Nullen mehr
inc R0
ret
;
; LcdDec schreibt die Zahl R3:R2 in Dezimal auf das Display
; 5, 4, 3 or 2 Ziffern werden dargestellt
;
LcdDec5:
clr R0 ; fuehrende Nullen unterdruecken
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall LcdDecDigit
LcdDec4:
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall LcdDecDigit
LcdDec3:
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall LcdDecDigit
LcdDec2:
clr ZH
ldi ZL,10
rcall LcdDecDigit
ldi rmp,'0'
add rmp,R2
rjmp LcdChar
;
; Ende der LCD-Routinen
;
; Lcd texte
;
; Init Text auf Display
;
LcdTxtInit1:
.DB " Akkulader V1.0 ",0
LcdTxtInit2:
.DB "(C)2005 by DG4FAC",0
LcdTxtInit3:
.DB "Vier Kanal Akku- ",0
LcdTxtInit4:
.DB " lader Prozessor ",0
;
; Ende der LCD Include-Datei
;

http://www.avr-asm-tutorial.net/akkuload/de/akkulcd.asm1/20/2009 7:50:59 PM
http://www.avr-asm-tutorial.net/akkuload/de/akkuuart.asm

; **************************************************************
; * Include-Datei fuer die UART-Kommandozeilen-Verarbeitung bei*
; * Akkuload (C)2005 by Gerh.Schmidt info@avr-asm-tutorial.net *
; **************************************************************
;
; Stellt die folgenden Routinen fuer die externe Verwendung bereit:
;
; Routine Register Funktion
; --------------------------------------------------------------
; UartInit rmp Initiiere den UART-Empfaenger und
; Sender
; UartSendChar Sendet das Zeichen in rmp ueber
; das UART
; UartSendOpenText rmp,R0,Z Sendet die Eroeffnungsmeldung beim
; Programmstart
; UartDec5 X,rmp Sendet die Binaerzahl in R3:R2 in
; UartDec4 Dezimalformat, R0>0: zeige
; UartDec3 fuehrende Nullen an
; UartDec2
;
; UartSendN5 X,rmp Sendet die Binaerzahl in R3:R2 in
; UartSendN4 Dezimalformat mit fester Laenge,
; UartSendN3 R0>0: zeigt fuehrende Nullen an
; UartSendN2
;
; UartHexB rmp Sendet das Hex Byte in rmp ueber das
; UART
; UartHex16 rmp,R0,Z Sendet 16 Bytes mit Adresse ab Z
; ueber das UART
; --------------------------------------------------------------
;
;
; Init UART
;
.EQU cUbrr = fClock/16/baud - 1 ; Baudratengenerator-Konstante
;
UartInit:
ldi rmp,HIGH(cUbrr) ; Init UART Baudratengenerator
out UBRRH,rmp
ldi rmp,LOW(cUbrr)
out UBRRL,rmp
ldi rmp,(1<<RXEN)|(1<<TXEN) ; Enable RX und TX
out UCSRB,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; 8N1
out UCSRC,rmp
in rmp,UDR; Loesche Rx-Zeilenpuffer
in rmp,UDR
in rmp,UDR
ldi rmp,LOW(sUartRxBs) ; Setze Pufferzeiger an Anfang
sts sUartRxBp,rmp
clr rmp ; Init aktuellen Kanal
sts sUartCurCh,rmp
clr rFlg ; Loesche Flag
ldi rmp,(1<<RXEN)|(1<<TXEN)|(1<<RXCIE) ; RX-Interrupts
out UCSRB,rmp
clr rmp
clr ZH
clr ZL
UartInit1:
sbiw ZL,1
brne UartInit1
dec rmp
brne UartInit1
ret
;
;
; **************** Subroutinen ********************************
;
; Sende das Zeichen in rmp an das UART
;
UartSendChar:
sbis UCSRA,UDRE ; warte auf leeres Senderegister
rjmp UartSendChar
out UDR,rmp ; sende das Zeichen in rmp
ret
;
; Sende den Text im Flash (Z zeigt darauf) an das UART
;
UartSendZ:
lpm ; lese naechstes Zeichen aus dem Flash
adiw ZL,1
tst R0 ; Null-Zeichen?
brne UartSendR0 ; Nein, sende
ret
UartSendR0:
mov rmp,R0 ; kopiere Zeichen
rcall UartSendChar ; sende Zeichen
rjmp UartSendZ ; naechstes Zeichen
;
; Sende Eroeffnungstext
;
UartSendOpenText:
ldi ZH,HIGH(2*UartTxtOpening) ; Zeiger Z auf Text
ldi ZL,LOW(2*UartTxtOpening)
rcall UartSendZ ; Sende den Text ab Z
lds R2,sEANm ; lese Anzahl der gespeicherten Akku-Id's
clr R3
clr R0
rcall UartSendN2 ; sende Anzahl Id's
ldi rmp,cCr ; Ende der Zeile
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
;
; Subtrahiere wiederholt und sende Zeichen wenn R0>0
;
UartSubt:
clr rmp ; Ergebnisregister
UartSubt1:
sub R2,XL ; subtrahiere LSB
sbc R3,XH ; subtrahiere MSB
brcs UartSubt2
inc rmp
rjmp UartSubt1
UartSubt2:
add R2,XL ; addiere wieder
adc R3,XH
add R0,rmp
breq UartSubt3
subi rmp,-'0' ; addiere ASCII-Null
rcall UartSendChar
UartSubt3:
ret
;
; Sende eine Biaerzahl ueber das UART, Zahl ist in R3:R2
;
UartSendNmbr:
clr R0
UartDec5:
ldi XH,HIGH(10000)
ldi XL,LOW(10000)
rcall UartSubt
UartDec4:
ldi XH,HIGH(1000)
ldi XL,LOW(1000)
rcall UartSubt
UartDec3:
clr XH
ldi XL,100
rcall UartSubt
UartDec2:
clr XH
ldi XL,10
rcall UartSubt
ldi rmp,'0'
add rmp,R2
rjmp UartSendChar
;
; Sende eine feste Anzahl Dezimalziffern
;
UartSubN:
clr rmp ; Ergebnisregister
UartSubN1:
sub R2,XL ; subtrahiere LSB
sbc R3,XH ; subtrahiere MSB
brcs UartSubN2
inc rmp
rjmp UartSubN1
UartSubN2:
add R2,XL ; addiere wieder
adc R3,XH
add R0,rmp
subi rmp,-'0' ; addiere ASCII-Null
tst R0
brne UartSubN3
ldi rmp,' '
UartSubN3:
rjmp UartSendChar
;
; Sende eine Zahl in R3:R2 mit fester Laenge
;
UartSendN5:
ldi XH,HIGH(10000)
ldi XL,LOW(10000)
rcall UartSubN
UartSendN4:
ldi XH,HIGH(1000)
ldi XL,LOW(1000)
rcall UartSubN
UartSendN3:
clr XH
ldi XL,100
rcall UartSubN
UartSendN2:
clr XH
ldi XL,10
rcall UartSubN
ldi rmp,'0'
add rmp,R2
rjmp UartSendChar
;
; Sendet ein Byte in rmp in Hex ueber das UART
;
UartHexB:
push rmp ; sichere Byte
swap rmp
rcall UartHexN
pop rmp ; stelle Bye wieder her
UartHexN:
andi rmp,0x0F
cpi rmp,10
brcs UartHexN1
subi rmp,-7
UartHexN1:
subi rmp,-'0'
rjmp UartSendChar
;
; UartHex16 sendet 16 Bytes in Hex ab Z
;
UartHex16:
mov rmp,ZH
rcall UartHexB
mov rmp,ZL
rcall UartHexB
ldi rmp,16
mov R0,rmp
UartHex16a:
ldi rmp,' ';
rcall UartSendChar
ld rmp,Z+
rcall UartHexB
dec R0
brne UartHex16a
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartSendCursor
;
; UART Kommandozeile bearbeitet, stelle RX-Puffer wieder her, sende Cursor
;
UartRxRet:
ldi rmp,LOW(sUartRxBs) ; Setze Pufferzeiger auf Anfang
sts sUartRxBp,rmp
cbr rFlg,(1<<bUartRxLine) ; loesche Zeilenflagge
UartSendCursor:
ldi rmp,'A' ; sende aktuellen Kanal
rcall UartSendChar
lds rmp,sUartCurCh
subi rmp,-'1' ; addiere ASCII-Eins
rcall UartSendChar
ldi rmp,'>' ; sende Cursor
rjmp UartSendChar
;
; Uebeliest fuehrende Nullen, Gleichheitszeichen, Anfuehrungszeichen und Komma
; kehrt mit gesetztem Carry zurueck und Fehlermeldung in Z zurueck, wenn
; vorzeitig das Ende der Zeile erreicht wird
;
UartSkipLeading:
lds R1,sUartRxBp ; lese Ende der Eingabezeile
UartSkipLeading1:
cp XL,R1
brcs UartSkipLeading2 ; nicht am Ende
ldi ZH,HIGH(2*UartTxtUnexEol) ; Fehl•rmeldung
ldi ZL,LOW(2*UartTxtUnexEol)
sec ; setze Carry
ret
UartSkipLeading2:
ld rmp,X+ ; lese Zeichen von der Zeile
cpi rmp,'=' ; Gleichheitszeichen?
breq UartSkipLeading1
cpi rmp,',' ; Komma?
breq UartSkipLeading1
cpi rmp,' ' ; Leerzeichen?
breq UartSkipLeading1
cpi rmp,'"' ; Anfuehrungszeichen?
breq UartSkipLeading1
sbiw XL,1
clc ; kein Ende der Zeile
ret
;
; Hole naechste Ziffer einer Dezimalzahl, Carry gesetzt bei Zeilenende, Zero
; gesetzt bei Ende der Zahl
;
UartGetDigit:
lds R1,sUartRxBp ; lese Ende der Eingabezeile
cp XL,R1
brcs UartGetDigit1 ; nicht am Ende
ldi ZH,HIGH(2*UartTxtUnexEol) ; Fehlermeldung
ldi ZL,LOW(2*UartTxtUnexEol)
sec ; setze Carry
ret
UartGetDigit1:
ld rmp,X+ ; lese Ziffer
cpi rmp,' ' ; Leerzeichen, Ende der Zahl?
breq UartGetDigitEnd
cpi rmp,cCr ; Ende der Zeile?
breq UartGetDigitEnd
cpi rmp,',' ; Komma?
breq UartGetDigitEnd
subi rmp,'0' ; mache Binarziffer
brcs UartGetDigitIll
cpi rmp,10 ; zu gross?
brcc UartGetDigitIll
clc ; alles ok
clz
ret
UartGetDigitIll:
ldi ZH,HIGH(2*UartTxtNmbrErr) ; Ungueltiges Zeichen in der Zahl
ldi ZL,LOW(2*UartTxtNmbrErr)
sec ; setze Carry fuer Fehler
UartGetDigitEnd:
ret
;
; Hole Dezimalzahl von der Empfangszeile
;
UartGetDec:
rcall UartSkipLeading
brcs UartGetDec3 ; Kehre mit gesetztem Carry zurueck, wenn Fehler
clr R2 ; Resultat LSB
clr R3 ; Resultat MSB
UartGetDec1:
rcall UartGetDigit ; lese die naechst Ziffer
brcs UartGetDec3 ; kehre mit gesetztem Carry zurueck, Fehler
breq UartGetDec4 ; Ende der Zahl erreicht
mov R0,R2 ; Kopiere Zwischenergebnis
mov R1,R3
add R2,R2 ; Ergebnis*2
adc R3,R3
brcs UartGetDec2 ; Zahlenueberlauf
add R2,R2 ; Ergebnis*4
adc R3,R3
brcs UartGetDec2 ; Zahlenueberlauf
add R2,R0 ; Ergebnis*5
adc R3,R1
brcs UartGetDec2 ; Zahlenueberlauf
add R2,R2 ; Ergebnis*10
adc R3,R3
brcs UartGetDec2 ; Zalenueberlauf
add R2,rmp ; addiere Ziffer
ldi rmp,0
adc R3,rmp
brcc UartGetDec1 ; Kein Zahlenueberlauf, naechste Ziffer
UartGetDec2:
ldi ZH,HIGH(2*UartTxtNmbrOvf) ; Zahlenueberlauf
ldi ZL,LOW(2*UartTxtNmbrOvf)
sec ; Carry setzen
UartGetDec3: ; Zahlenfehler
ret
UartGetDec4: ; Zahl ist ok und komplett
clc ; Carry loeschen
ret
;
; ****************** Empfangszeile **********************
;
; Eine vollstaendge Emfangszeile empfangen, antworte
;
UartRxLine:
ldi rmp,LOW(UartRxRet) ; Rueckkehradresse UartRxRet auf Stapel
push rmp
ldi rmp,HIGH(UartRxRet)
push rmp
ldi ZH,HIGH(2*UartCmds) ; Z zeigt auf Befehlsliste
ldi ZL,LOW(2*UartCmds)
UartRxLine1:
lpm ; Ende der Befehlsliste?
mov rmp,R0 ; FF signalisiert Ende der Liste
cpi rmp,0xFF
brne UartRxLine3
UartRxLine2: ; Ende der Befehlsliste, unbekannter Befehl
ldi ZH,HIGH(2*UartTxtUnkCmd) ; Sende Fehlermeldung
ldi ZL,LOW(2*UartTxtUnkCmd)
rjmp UartSendZ
UartRxLine3: ; beginne Vergleich
ldi XH,HIGH(sUartRxBs) ; X auf emfangene Zeile
ldi XL,LOW(sUartRxBs)
UartRxLine4:
lds rmp,sUartRxBp ; Pufferzeiger lesen
cp XL,rmp ; Ende des Puffers erreicht?
brcs UartRxLine7 ; nein, weiter
UartRxLine5: ; ueberspringe diesen Befehl, gehe zum naechsten
lpm ; lese naechstes Befehlszeichen
adiw ZL,1 ; Z auf naechstes Zeichen
mov rmp,R0 ; Endezeichen fuer Befehl?
cpi rmp,'#' ; Endzeichen erreicht?
brne UartRxLine5 ; nein
lpm ; Ist das naechste Zeichen ein Leerzeichen?
mov rmp,R0
cpi rmp,' '
brne UartRxLine6 ; nein
adiw ZL,1
UartRxLine6:
adiw ZL,7 ; springe ueber die Adressen
rjmp UartRxLine1 ; naechster Befehl
UartRxLine7:
lpm ; lese Zeichen aus Flash
mov rmp,R0 ; kopiere
cpi rmp,'#' ; Ende des Befehls?
breq UartRxLine8 ; ja
ld rmp,X+ ; lese naechstes Zeichen aus Puffer
sbr rmp,0x20 ; in Kleinbuchstabe
cp rmp,R0 ; Vergleich des Zeichens
brne UartRxLine5 ; nicht gleich, springe zum naechsten Befehl
adiw ZL,1 ; naechstes Zeichen
rjmp UartRxLine4 ; naechstes Zeichen im Puffer pruefen
UartRxLine8:
adiw ZL,1 ; Leerzeichen hinter #?
lpm
mov rmp,R0
cpi rmp,' '
brne UartRxLine9 ; nein
adiw ZL,1 ; ja
UartRxLine9:
lds rmp,sUartRxBp ; Ende des Puffers erreicht?
cpc XL,rmp
brcc UartRxLine2
ld rmp,X+ ; lese naechstes Zeichen aus Puffer
cpi rmp,cCr ; Ende der Zeile?
brne UartRxLine10 ; mit Parameter
; Befehl ohne Parameter
adiw ZL,5 ; Zeige Z auf Addresse
lpm ; lese LSB
push R0 ; auf Stapel
adiw ZL,1 ; lese MSB
lpm
push R0 ; auf Stapel
clc ; keine Parameter
ret ; springe zum Befehl
UartRxLine10: ; Befehlszeile mit Parameter
cpi rmp,'=' ; Parameter?
brne UartRxLine5 ; Nein, suche naechsten Befehl
lpm ; lese Anzahl Parameter
tst R0
brne UartRxLine11 ; Befehl hat Parameter
ldi ZH,HIGH(2*UartTxtParaErr) ; Fehlermeldung
ldi ZL,LOW(2*UartTxtParaErr)
rjmp UartSendZ
UartRxLine11: ; Kommadozeilenparameter
rcall UartGetDec ; hole Dezimalzahl
brcc UartRxLine17 ; Zahl ist ok
rjmp UartSendZ ; Fehlermeldung
UartRxLine17:
adiw ZL,1 ; lese LSB minimum Parameter
lpm
adiw ZL,1
cp R2,R0 ; vergleiche LSB
lpm ; lese MSB minimum Parameter
cpc R3,R0 ; vergleiche MB
brcs UartRxLine18
adiw ZL,1 ; lese LSB maximum Parameter
lpm
adiw ZL,1
sec ; Setze Carry fuer Max+1
cpc R2,R0 ; vergleiche LSB
lpm ; lese MSB max Parameter
cpc R3,R0 ; vergleiche MSB
brcs UartRxLine19 ; Zahl ist ok
UartRxLine18: ; Zahl au•rhalb des zulaessigen Bereichs
ldi ZH,HIGH(2*UartTxtNmbrOor)
ldi ZL,LOW(2*UartTxtNmbrOor)
rjmp UartSendZ
UartRxLine19: ; lese Adresse und springe
adiw ZL,1 ; lese LSB
lpm
push R0 ; LSB auf Stapel
adiw ZL,1 ; lese MSB
lpm
push R0 ; MSB auf Stapel
sec ; setze Carry, Parameter
ret ; springe an Befehlsadresse
;
; ***************** Befehle *********************************
;
; UART-Befehl HILFE
;
UartHelp:
ldi ZH,HIGH(2*UartTxtHelp) ; Hilfetext
ldi ZL,LOW(2*UartTxtHelp)
rjmp UartSendZ
;
; UART-Befehl RESTART
;
UartRestart:
pop rmp ; Loesche Ruecksprungadresse
pop rmp
jmp 0 ; starte neu
;
; UART-Befehl Kanal
;
UartChannel:
brcc UartChannel1
dec R2
sts sUartCurCh,R2
UartChannel1: ; gib aktuellen Kanal aus
ldi ZH,HIGH(2*UartTxtCurrCh)
ldi ZL,LOW(2*UartTxtCurrCh)
rcall UartSendZ
lds rmp,sUartCurCh ; lese aktuellen Kanal
subi rmp,-'1' ; addiere ASCII-Eins
rcall UartSendChar
adiw ZL,1 ; vervollstaendige Ausgabe
rjmp UartSendZ
;
; Holt die aktuelle Akku-Id-Adresse des Kanals
;
UartGetAkkuId:
ldi ZH,HIGH(sAdcAI1) ; Z auf Akku-Id 1
ldi ZL,LOW(sAdcAI1)
lds rmp,sUartCurCh
add ZL,rmp
add ZL,rmp
ret
;
; Setze die Akku-Id des aktuellen Kanals
;
UartAkkuId:
brcc UartAkkuId1
rcall UartGetAkkuId
st Z,R2
lds R0,sUartCurCh
call IdSetPar
UartAkkuId1:
ldi ZH,HIGH(2*UartTxtAkkuId)
ldi ZL,LOW(2*UartTxtAkkuId)
rcall UartSendZ
rcall UartGetAkkuId
ld R2,Z
clr R3
clr R0
rcall UartDec2
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartOutSettings
;
; Zeiger rmp auf das Entladebit
;
UartUnloadBit:
lds R0,sUartCurCh
ldi rmp,0x10
UartUnloadBit1:
tst R0
breq UartUnloadBit2
lsl rmp
dec R0
rjmp UartUnloadBit1
UartUnloadBit2:
;
; Zeige mit X auf das PWM-Register
;
UartChannX:
clr XH ; Zeiger MSB is Null
ldi XL,cPwm1S ; LSB auf LSB der PWM von Kanal Eins
lds R0,sUartCurCh ; addiere Kanal
add XL,R0
ret
;
; Aktuelle UART Parameteradresse in X
;
UartGetChPar:
lds R1,sUartCurCh ; lese Kanal
lsl R1 ; *2
lsl R1 ; *4
lsl R1 ; *8
ldi XH,HIGH(sCh1UV) ; Basisaddresse Entladespannung
ldi XL,LOW(sCh1UV)
add XL,R1 ; addieren
brcc UartGetChPar1
inc XH
UartGetChPar1:
ret
;
; Hole Adresse des Kanalstatus-Textes in Z
;
UartGetChAct:
ldi ZH,HIGH(2*UartTxtAct)
ldi ZL,LOW(2*UartTxtAct)
lds R1,sUartCurCh ; aktueller Kanal
lds rmp,sState ; Kanalstatus
UartGetChAct1:
tst R1
breq UartGetChAct2
lsr rmp
lsr rmp
dec R1
rjmp UartGetChAct1
UartGetChAct2:
andi rmp,0x03 ; isoliere Bits
breq UartGetChAct4
UartGetChAct3:
lpm
adiw ZL,1
tst R0
brne UartGetChAct3
dec rmp
rjmp UartGetChAct2
UartGetChAct4:
ret
;
; Setze die Entladespannung
;
UartSetU:
brcc UartSetU1
rcall UartGetChPar ; Adresse in X
st X+,R2 ; speichere Parameter dort
st X,R3
UartSetU1:
rjmp UartOutSettings
;
; Setze den Ladestrom dieses Kanals
;
UartSetI:
brcc UartSetI1
rcall UartGetChPar ; Adresse in X
adiw XL,2 ; Ladestrom ist der zweite Parameter
st X+,R2 ; speichere die empfangene Zahl dort
st X,R3
UartSetI1:
rjmp UartOutSettings
;
; Setze die Kapazitaet
;
UartSetW:
brcc UartSetW1 ; kein Parameter angegeben
rcall UartGetChPar ; hole Adresse in X
adiw XL,4 ; Kapazitaet ist der dritte Parameter
st X+,R2 ; speichern der empfangenen Zahl
st X,R3
UartSetW1:
rjmp UartOutSettings
;
; Setze den Erhaltungsstrom
;
UartSetM:
brcc UartSetM1
rcall UartGetChPar ; Adresse in X
adiw XL,6 ; vierte Variable
st X+,R2 ; speichern des Parameters
st X,R3
UartSetM1:
rjmp UartOutSettings
;
; Setze den Status auf den Wert in rmp
; Anfang: rmp Bit 1 und 0 = Aktivitaetsflags
;
UartSetState:
lds R0,sUartCurCh ; Kanal nach R0
lds R2,sState ; statusbits nach R2
mov R3,rmp ; OR-Maske in R3 speichern
ldi rmp,0xFC ; Maske fuer AND erstellen
mov R1,rmp
mov rmp,R3 ; Original wieder herstellen
UartSetState1:
tst R0 ; Kanal erreicht?
breq UartSetState2
sec ; naechste Kanal
rol R1
sec
rol R1
lsl rmp ; Soll-Statusbits zwei links schieben
lsl rmp
lsr R2 ; Ist-Status-Bits zwei rechts
lsr R2
dec R0
rjmp UartSetState1
UartSetState2:
lds R0,sState
and R0,R1 ; beide Bits loeschen
or R0,rmp ; neue Bts setzen
sts sState,R0
mov rmp,R2 ; vorherigen Status pruefen
andi rmp,0x03 ; isoliere Statusbits
cp rmp,R3 ; Status veraendert?
breq UartSetState4 ; nein, ueberspringe Korrektur
lds R0,sUartCurCh ; R0 ist aktueller Kanal
cpi rmp,0x02 ; vorher im Ladezustand?
brne UartSetState3 ; inaktiv, Entladen oder Erhaltungsladen
call EpStore ; geladene Kapazitaet im EEPROM speichern
sec
UartSetState3: ; loesche akkumulierte Kapazitaet, wenn inaktiv oder Laden
call ClearCap ; Kapazitaet in Kanal R0 loeschen
UartSetState4:
rjmp UartOutSettings
;
; Setze Statusbits auf AUS
;
UartClear:
ldi rmp,0x00
rjmp UartSetState
;
; Setze das Entladebit und loesche die PWM
;
UartUnload:
rcall UartUnloadBit
or rPwmOut,rmp
clr rmp
st X,rmp
ldi ZH,HIGH(2*UartTxtUnload)
ldi ZL,LOW(2*UartTxtUnload)
rcall UartSendZ
ldi rmp,0x01 ; Entladeflagge
rjmp UartSetState
;
; Statusbits auf Erhaltungsladung
;
UartMaint:
ldi rmp,0x03
rjmp UartSetState
;
; Starte Ladevorgang
;
UartLoad:
ldi rmp,0x02
rjmp UartSetState
;
; Gib alle Einstellungen im Kanal auf dem UART aus
;
UartOutSettings:
ldi rmp,4 ; R4 ist Zaehler
mov R4,rmp
ldi ZH,HIGH(2*UartTxtSettings)
ldi ZL,LOW(2*UartTxtSettings)
rcall UartSendZ
lds R1,sUartCurCh
ldi rmp,'1'
add rmp,R1
rcall UartSendChar
rcall UartSendZ
ldi XH,HIGH(sAdcAI1) ; Schreibe Id
ldi XL,LOW(sAdcAI1)
lds rmp,sUartCurCh
add XL,rmp
add XL,rmp
ld R2,X
clr R3
rcall UartSendNmbr
rcall UartSendZ
push ZH
push ZL
rcall UartGetChAct ; schreibe Statustext
rcall UartSendZ
pop ZL
pop ZH
rcall UartSendZ
rcall UartGetChPar ; schreibe alle Parameter
UartOutSettings1:
ld R2,X+
ld R3,X+
push XH
push XL
rcall UartSendNmbr
rcall UartSendZ
pop XL
pop XH
dec R4
brne UartOutSettings1
ret
;
; Texte fuer die Ausgabe der Einstellungen
;
UartTxtSettings:
.DB "Ch ",0
.DB ": Id=",0
.DB ", Status=",0
.DB ", U= ",0
.DB "mV, I= ",0
.DB "mA, C= ",0
.DB "mAh, Im= ",0
.DB "mA",$0D,$0A,$00,$00
;
; Aktivitaetsstatus des Kanals
;
UartTxtAct:
.DB "abgeschaltet ",0
.DB "Entladen ",0
.DB "Laden",0
.DB "Erhaltung",0
;
; Schalte Monitoring um
;
UartMoniOn:
ldi rmp,1<<bUMoni ; Moniflag-Maske
eor rFlgD,rmp ; umschalten
ldi ZH,HIGH(2*UartTxtMoniOff) ; Monitor aus ausgeben
ldi ZL,LOW(2*UartTxtMoniOff)
sbrs rFlgD,bUMoni
rjmp UartMoniOn1
ldi ZH,HIGH(2*UartTxtMoniOn) ; Monitor an ausgeben
ldi ZL,LOW(2*UartTxtMoniOn)
rcall UartSendZ
rjmp DispTimeUd ; Systemzeit ueber UART ausgeben
UartMoniOn1: ; Monitoring umgeschaltet
rjmp UartSendZ
;
; Setze die PWM eines Kanals
;
UartPwm:
brcc UartPwm1
rcall UartUnloadBit
st X,R2 ; setze aktuellen Kanalwert
com rmp
and rPwmOut,rmp ; PWM-Ausgabe setzen
UartPwm1:
ldi ZH,HIGH(2*UartTxtPwm) ; Text fuer PEWM-Ausgabe
ldi ZL,LOW(2*UartTxtPwm)
rcall UartSendZ
rcall UartUnloadBit ; Entladebit lesen
ld R2,X
clr R3
rcall UartSendNmbr
adiw ZL,1
rjmp UartSendZ
;
; Neue Akku-Id erzeugen
;
UartNew:
brcs UartNew2 ; erster parameter ok
ldi ZH,HIGH(2*UartTxtNewParamErr) ; Parameterfehler
ldi ZL,LOW(2*UartTxtNewParamErr)
UartNew1: ; Fehlermeldung in Z
rjmp UartSendZ
UartNew2:
lds rmp,sEANm ; Anzahl an Id's lesen
cpi rmp,cEepMax+1 ; mt Maximalzahl vergleichen
brcc UartNew8 ; zu viele Id's
ldi ZH,HIGH(sEAId) ; Z auf Puffer setzen
ldi ZL,LOW(sEAId)
lds rmp,sEANm ; Zahl der Id's lesen
inc rmp ; naechste Akku-Id
st Z,rmp ; in Puffer
adiw ZL,2 ; zeige auf Kapazitaet
st Z+,R2 ; Kapazitaet in R3:R2 in Puffer
st Z,R3
sbiw ZL,2 ; auf Akkutyp zeigen
rcall UartGetDec ; Groesze aus Zeile lesen
brcs UartNew1 ; Fehler
tst R3 ; Groesze pruefen
brne UartNew3 ; MSB>0, falsch
mov rmp,R2
cpi rmp,4 ; Groesze kleiner 4?
brcs UartNew4 ; ja, ok
UartNew3: ; falsche Groesze
ldi ZH,HIGH(2*UartTxtNewSize) ; Fehlermeldung
ldi ZL,LOW(2*UartTxtNewSize)
rjmp UartSendZ
UartNew4:
subi rmp,-0xA0 ; A0 zu Groesze addieren $$!!$$
st Z,rmp ; Groesze speichern
adiw ZL,3 ; auf Anzahl Ladevorgaenge zeigen
rcall UartGetDec ; Anzahl Ladevorgaenge aus Zeile
brcs UartNew1 ; Fehler
st Z+,R2 ; in Puffer speichern
st Z+,R3
clr rmp
st Z+,rmp ; Restkapazitaet loeschen
st Z+,rmp
rcall UartSkipLeading ; ueber Trennzeichen hinweglesen
brcs UartNew1 ; Fehler
ldi rmp,8 ; 8 Byte Text lesen
mov R0,rmp
UartNew5:

http://www.avr-asm-tutorial.net/akkuload/de/akkuuart.asm (1 of 2)1/20/2009 7:51:03 PM


http://www.avr-asm-tutorial.net/akkuload/de/akkuuart.asm

ld rmp,X+ ; lese Textzeichen


cpi rmp,'"' ; Ende des Texts?
breq UartNew6 ; ja
cpi rmp,cCr ; Ende der Zeile?
breq UartNew6 ; ja
st Z+,rmp ; Zeichen in Puffer speichern
dec R0 ; Zeichenzaehler
brne UartNew5 ; naechstes Zeichen
rjmp UartNew7 ; Rest ueberlesen
UartNew6:
tst R0 ; Anzahl Zeichen auf 8 auffuellen
breq UartNew7
ldi rmp,' '
st Z+,rmp
dec R0
rjmp UartNew6
UartNew7:
call EpWrite ; Puffer ins EEPROM schreiben
lds rmp,sEANm ; Anzahl Id's erhoehen
inc rmp
sts sEANm,rmp ; und speichern
ldi ZH,HIGH(2*UartTxtList) ; Header
ldi ZL,LOW(2*UartTxtList)
rcall UartSendZ
lds rmp,sEAId ; Anzahl Id's ausgeben
rjmp UartList1
UartNew8: ; Fehler zu viele Id's
ldi ZH,HIGH(2*UartTxtNewMany)
ldi ZL,LOW(2*UartTxtNewMany)
rjmp UartSendZ
;
; Auflisten der gespecherten Akku-Id's
;
UartList:
ldi ZH,HIGH(2*UartTxtList) ; Header
ldi ZL,LOW(2*UartTxtList)
rcall UartSendZ
clr R6 ; R6 ist Zaehler
UartList1:
inc R6
lds R0,sEANm ; lese Anzahl Id's
sec
cpc R6,R0 ; Ende der Liste?
brcc UartList3
mov rmp,R6
call EpRead ; Id in rmp aus EEPROM lesen
ldi ZH,HIGH(sEAId) ; Z auf Puffer
ldi ZL,LOW(sEAId)
ld R2,Z+ ; kopiere Id-Nummer
clr R3
clr R0
rcall UartSendN2
ldi rmp,' '
rcall UartSendChar
ld rmp,Z+ ; Schreibe Akkugroesze
rcall UartHexB
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Schreibe Nennkapazitaet
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Schreibe Anzahl Volladungen
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Schreibe Restkapazitaet
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ldi rmp,8
mov R1,rmp
UartList2:
ld rmp,Z+ ; Lese Text
rcall UartSendChar
dec R1
brne UartList2
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartList1 ; und weiter
UartList3:
ret
;
; ***************** Tabellen ************************
;
; Befehle, Parameter und Adresstabelle fuer UART-Befehle
;
UartCmds:
.DB "hilfe# ",0 ; HILFE.-Befehl, keine Parameter
.DW 0,0,UartHelp
.DB "a# ",1 ; Akku Kanalwahl
.DW 1,4,UartChannel
.DB "n# ",1 ; Akku-Id
.DW 0,32,UartAkkuId
.DB "u# ",1 ; Entlade-Abschaltspannung
.DW 700,1200,UartSetU
.DB "i# ",1 ; Ladestrom in mA
.DW 5,350,UartSetI
.DB "c# ",1 ; Kapazitaet in mAh
.DW 10,2500,UartSetW
.DB "m# ",1 ; Erhaltungsstrom in mA
.DW 5,100,UartSetM
.DB "aus# ",0 ; Kanal abschalten
.DW 0,0,UartClear
.DB "entladen#",0 ; Entladen
.DW 0,0,UartUnload
.DB "laden# ",0 ; Laden
.DW 0,0,UartLoad
.DB "erhalten#",0 ; Erhalten
.DW 0,0,UartMaint
.DB "monitor# ",0 ; Monitor ein/aus
.DW 0,0,UartMoniOn
.DB "pwm# ",1 ; PWM-Wert setzen
.DW 0,255,UartPwm
.DB "neu# ",1 ; neue Akku-Id erzeugen
.DW 100,9000,UartNew
.DB "liste# ",0 ; Liste der gespeicherten Akkus
.DW 0,0,UartList
.DB "neustart#",0 ; RESTART-Befehl, keine Parameter
.DW 0,0,UartRestart
.DW $FFFF ; Ende der Befehlsliste
;
; UART Texte
;
UartTxtHelp:
.DB "Akkuload Befehlsliste:",$0D,$0A
.DB "<hilfe>, kein param: diese Liste. ",$0D,$0A
.DB "<a> oder <a=x>, param x (1..4): lese/setze Kanalnummer. ",$0D,$0A
.DB "<n> oder <n=x>, param x (1..32): lese/setze Akku-Id.",$0D,$0A
.DB "<u> oder <u=x>, param x (700..1200): lese/setze Entladespannung.",$0D,$0A
.DB "<i> oder <i=x>, param x (5..175): lese/setze Ladestrom in mA. ",$0D,$0A
.DB "<c> oder <c=x>, param x (10..9999): lese/setze Kapazitaet in mAh. ",$0D,$0A
.DB "<m> oder <m=x>, param x (5..100): lese/setze Erhaltungsstrom in mA",$0D,$0A
.DB "<aus>, kein param: schalte Kanal ab.",$0D,$0A
.DB "<entlade>, kein param: schalte Entladen ein.",$0D,$0A
.DB "<lade>, kein param: starte laden. ",$0D,$0A
.DB "<erhalten>, kein param: schalte Erhaltungsladung ein. ",$0D,$0A
.DB "<monitor>, kein param: schalte monitoring ein/aus.",$0D,$0A
.DB "<pwm> oder <pwm=x>, param x (0..255): setze PWM-Wert. ",$0D,$0A
.DB "<neu=Kapazitaet, Groesze, Ladungen, Text> erzeugt neue Id,",$0D,$0A
.DB " Kapazitaet 100..9000, Groesze 0..3, Ladungen 0..65535, Text frei.",$0D,$0A
.DB "<liste>, kein param: Liste aller gespeicherten Akku-Id's. ",$0D,$0A
.DB "<neustart>, kein param: Neustart des Controllers.",$0D,$0A,$00
;
UartTxtOpening:
.DB " "
.DB $0C,$0C,$0D,$0A
.DB "Akkulader (C)2005 by info@avr-asm-tutorial.net",$0D,$0A
.DB "----------------------------------------------",$0D,$0A
.DB "Gespeicherte Akku-Id's : ",$00
.DB "Gib 'hilfe' <RETURN> fuer Menue ein.",$0D,$0A
;
UartTxtUnkCmd:
.DB "Unbekannter Befehl!",$0D,$0A,$00
;
UartTxtParaErr:
.DB "Befehl hat keine Parameter!",$0D,$0A,$00
;
UartTxtUnexEol:
.DB "Unerwartetes Ende der Zeile! ",$0D,$0A,$00
;
UartTxtNmbrErr:
.DB "Unzulaessiges Zeichen in Zahl! ",$0D,$0A,$00
;
UartTxtNmbrOvf:
.DB "Zahlenueberlauf! ",$0D,$0A,$00
;
UartTxtNmbrOor:
.DB "Zahl ausserhalb des zulaessigen Bereichs!",$0D,$0A,$00
;
UartTxtCurrCh:
.DB "Derzeitiger Akkukanal ist : ",$00,$20
.DB " ",$0D,$0A,$00
;
UartTxtPwm:
.DB "Derzeitiger PWM-Wert ist : ",$00
.DB " ",$0D,$0A,$00
;
UartTxtUnload:
.DB "Entladen eingeschaltet.",$0D,$0A,$00
;
UartTxtMoniOff:
.DB "Monitoring ist aus.",$0D,$0A,$00
;
UartTxtMoniOn:
.DB "Monitoring ist an. ",$0D,$0A,$00
;
UartTxtList:
.DB "Id Gr Kapaz Ladg. _Rest Text____",$0D,$0A,$00,$00
;
UartTxtAkkuId:
.DB "Aktuelle Id ist ",$00,$00
;
UartTxtNewParamErr:
.DB "Vermisse alle Parameter! ",$0D,$0A,$00
;
UartTxtNewSize:
.DB "Ungueltige Groesze!",$0D,$0A,$00
;
UartTxtNewMany:
.DB "Zu viele Akku-Id's! ",$0D,$0A,$00,$00
;
;
; Ende der UART-Include-Datei
;

http://www.avr-asm-tutorial.net/akkuload/de/akkuuart.asm (2 of 2)1/20/2009 7:51:03 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkuload.asm

; **************************************************************
; * Akkuloader Version 0.1 for ATmega16 @ 8 Mcs/s clock *
; * (C)2005 by Gerh.Schmidt info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "m16def.inc"
;
; Constants
;
.EQU fclock = 8000000 ; processor clock frequency
.EQU baud = 9600 ; Serial communication baudrate
.EQU cUartTime = 5 ; send system time over Uart any 5 minutes
.EQU cKeyRep = 5 ; number of correct keys until key is accepted
.EQU cUnlVol = 1000 ; default unload threshhold voltage in mV
;
; Register definitions
;
; R0 used as register for flash operations
; R1:R0 used as double register in calculations
; R3:R2 dto.
; R6:R5:R4 used as triple register in calculations
.DEF rKeyLst = R7 ; Last key read
.DEF rKeyRep = R8 ; counter for key repeat
;.DEF rAdcV = R9 ; Operating voltage mask of the ADC
.DEF rPwmC = R10 ; PWM counter
.DEF rPwm1S = R11 ; PWM switch value for Channel 1
.EQU cPwm1S = 11 ; Value for calculating channel register
.DEF rPwm2S = R12 ; PWM switch value for Channel 2
.DEF rPwm3S = R13 ; PWM switch value for Channel 3
.DEF rPwm4S = R14 ; PWM switch value for Channel 4
.DEF rSreg = R15 ; Save SREG during ints
.DEF rmp = R16 ; Multipurpose register
.DEF rimp = R17 ; Multipurpose register during interrupts
.DEF rimp1 = R18 ; Multipurpose register during interrupts
.DEF rFlg = R19 ; Multipurpose flag register
.DEF rFlgD = R20 ; Display flag register
.DEF rPwmOut= R21 ; Value for Port Out
; Free R22..R23
.DEF rChCL = R24 ; channel counter, LSB
.DEF rChCH = R25 ; dto., MSB
; X (R27:R26) used for purposes outside Ints
; Y (R29:R28) used for ADC channel calculations
; Z (R31:R30) used for purposes outside Ints
;
; Bit definitions for rFlg
.EQU bUartRxLine = 7 ; a complete line has been received
.EQU bLcdOk = 6 ; Lcd is connected and detected ok
; not used: bit 4 and 5
.EQU bMin = 2 ; timer reached 1 Minute
.EQU b32m = 1 ; timer int 4 seconds, 32 Adc conversions complete
.EQU b64Hz = 0 ; timer int 64 Hz tick
;
; Bit definitions for the display flag rFlgD
;
.EQU bUHex = 7 ; display results in hex over Uart (debug)
.EQU bUMoni = 6 ; monitor active channels over Uart
.EQU bURdy = 5 ; results ready for Uart display
.EQU bLRdy = 4 ; results ready for Lcd display
.EQU bLcd3 = 3 ; Display results in line 4
.EQU bLcd2 = 2 ; Display results in line 3
.EQU bLcd1 = 1 ; Display results in line 2
.EQU bLcd0 = 0 ; Display results in line 1
;
;
; Calculated constants
;
.EQU cTC1Prsc = 8 ; TC1 Prescaler value
.EQU cTC1Div = fClock / cTC1Prsc / 64 ; 64 Ints per second
.EQU cTC1CompB = 50 ; Timer compare to start ADC
.EQU cStartAdc = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); Enable and clock=128
.EQU cRestartAdc = cStartAdc | (1<<ADSC)
.EQU cAdcV = 1<<REFS0 ; Set Adc reference voltage to 5V
.EQU cEepMax = 512/16 ; maximum number of stored akkus in Eeprom = 32
.EQU cCr = $0D ; Carriage return char
.EQU cLf = $0A ; Line feed char
;
; SRAM Positions
;
; Uart SRAM variables
.EQU sUartRxBp = $0060 ; UART Rx Buffer Pointer
.EQU sUartRxBs = $0061 ; Uart Rx Buffer start
.EQU sUartRxBe = $007E ; Uart Rx Buffer end
.EQU sUartCurCh = $007F ; Current Uart Channel
; Channel values
.EQU sCh1UV = $0080 ; Channel 1, minimum unloading voltage
.EQU sCh1LC = $0082 ; Ch 1, load current in mA
.EQU sCh1LW = $0084 ; Ch 1, max work to load in mAh
.EQU sCh1MC = $0086 ; Ch 1, maintain current in mA
.EQU sCh2UV = $0088 ; Ch 2, dto.
.EQU sCh2LC = $008A ; Ch 2, dto.
.EQU sCh2LW = $008C ; Ch 2, dto.
.EQU sCh2MC = $008E ; Ch 2, dto.
.EQU sCh3UV = $0090 ; Ch 3, dto.
.EQU sCh3LC = $0092 ; Ch 3, dto.
.EQU sCh3LW = $0094 ; Ch 3, dto.
.EQU sCh3MC = $0096 ; Ch 3, dto.
.EQU sCh4UV = $0098 ; Ch 4, dto.
.EQU sCh4LC = $009A ; Ch 4, dto.
.EQU sCh4LW = $009C ; Ch 4, dto.
.EQU sCh4MC = $009E ; Ch 4, dto.
; Measuring values
.EQU sAdcE1 = $00A0 ; Adc measuring results, even channels
.EQU sAdcO1 = $00A8 ; dto., odd channels
.EQU sAdcE4 = $00B0 ; Adc sum for 4 seconds, even channels
.EQU sAdcO4 = $00B8 ; dto., odd channels
.EQU sAdcU = $00C0 ; Voltages, even channels, then odd channels
.EQU sAdcI = $00D0 ; Load currents in mA
.EQU sAdcC = $00D8 ; mAh (LSB,MSB)
.EQU sAdcLL1= $00E0 ; mAh LLSB, Channel 1
.EQU sAdcAI1= $00E1 ; accu id, Channel 1
; Channel control
.EQU sState = $00E8 ; Current state of the channels, bits 44332211
; 00=nothing, 01:unloading, 10:loading, 11:maintaining
.EQU sTimeM = $00E9 ; System time, minutes (0, 15, 30, 45)
.EQU sTimeH = $00EA ; dto., hours
.EQU sTimeD = $00EB ; dto., days
.EQU sLcdCs = $00EC ; LCD cursor position
; Key input
.EQU sKeyNC = $00ED ; Decimal number input position
.EQU sKeyNW = $00EE ; Decimal number in and output word
.EQU sKeyNM = $00F0 ; Decimal number maximum value
.EQU sKeyJR = $00F2 ; Jump adress on number input ready
.EQU sKeyJS = $00F4 ; Jump adress on skip number input
.EQU sKeyJ1 = $00F6 ; Jump adress on key 1
.EQU sKeyJ2 = $00F8 ; dto., key 2
.EQU sKeyJ3 = $00FA ; dto., key 3
.EQU sKeyCh = $00FC ; Selected channel for sets and commands
; LED output
.EQU sLedC = $00FD ; Led counter
.EQU sLed1 = $00FE ; Led channel 1 compare value
.EQU sLed2 = $00FF ; dto., channel 2
.EQU sLed3 = $0100 ; dto., channel 3
.EQU sLed4 = $0101 ; dto., channel 4
; EEPROM buffer
.EQU sEepB = $0102 ; EEPROM buffer for an akku record, 16 bytes
.EQU sEAId = $0102 ; EEPROM Akku Id
.EQU sESize = $0103 ; EEPROM Akku size = A0..A3
.EQU sENCL = $0104 ; EEPROM nominal capacity LSB
.EQU sENCM = $0105 ; dto., MSB
.EQU sENLL = $0106 ; EEPROM number of full loads, LSB
.EQU sENLM = $0107 ; dto., MSB
.EQU sENRL = $0108 ; EEPROM rest capacity in mAh, LSB
.EQU sENRM = $0109 ; dto., MSB
.EQU sEATxt = $010A ; Text portion of the akku definition
.EQU sENul = $0112 ; Null char as stop sign
.EQU sEANm = $0113 ; Number of stored akkus in Eeprom
;
; next free SRAM location: $0114
;
;
; Reset- and interrupt vectors
; (these are two words in the ATmega16!)
;
.CSEG
.ORG $0000
rjmp main ; Reset vector
nop
reti ; INT0 vector
nop
reti ; INT1 vector
nop
reti ; TC2Comp vector
nop
reti ; TC2Ovf vector
nop
reti ; TC1Capt vector
nop
rjmp TC1CmpAIsr ; TC1CompA vector
nop
rjmp TC1CmpBIsr ; TC1CompB vector
nop
reti ; TC1Ovf vector
nop
rjmp TC0OvfIsr ; TC0Ovf vector
nop
reti ; SPI, STC vector
nop
rjmp SioRxCIsr; USARTRxC vector
nop
reti ; USARTUdre vector
nop
reti ; USARTTxc vector
nop
reti ; ADC vector
nop
reti ; EE_RDY vector
nop
reti ; ANA_COMP vector
nop
reti ; TWI vector
nop
reti ; INT2 vector
nop
reti ; TC0Comp vector
nop
reti ; SPM_RDY vector
nop
;
; TC1 Compare A Int Service routine
; (Reads ADC result and stores it)
;
TC1CmpAIsr:
in rSreg,SREG ; Save SREG
sbr rFlg,1<<b64Hz ; set 64 tick flag
mov rimp,rChCL ; Check counter
andi rimp,1 ; odd or even channel?
brne TC1CmpAIsrO ; odd channel
; even channel
mov rimp,rChCL ; check counter
andi rimp,0xF8 ; isolate all but channel info
brne TC1CmpAIsrE1 ; no start condition
; TC1 has finished 32 cycles, starts new
in rimp,ADCL ; read ADC LSB
st Y,rimp ; store in Sram
in rimp,ADCH ; read ADC MSB
std Y+1,rimp ; store in Sram
rjmp TC1CmpAIsrE3
TC1CmpAIsrE1: ; not starting new
cpi rimp,0xF8 ; last measurement in channel?
breq TC1CmpAIsrE2 ; yes, add the last
; normal measurement, add to sum
in rimp1,ADCL ; read result LSB
ld rimp,Y ; read last sum
add rimp,rimp1 ; add new result
st Y,rimp ; store in Sram
in rimp1,ADCH ; read result MSB
ldd rimp,Y+1 ; read last sum MSB
adc rimp,rimp1 ; add to sum
std Y+1,rimp ; store in Sram
rjmp TC1CmpAIsrE3
TC1CmpAIsrE2: ; the last measurement of the series
in rimp1,ADCL ; read result
ld rimp,Y ; read last result
add rimp,rimp1 ; add to result
std Y+16,rimp ; store in sum Sram
in rimp1,ADCH ; read result MSB
ldd rimp,Y+1 ; load sum result MSB
adc rimp,rimp1 ; add MSB to result
std Y+17,rimp ; store in sum Sram MSB
TC1CmpAIsrE3:
adiw rChCL,1 ; next channel
mov rimp,rChCL ; copy counter
andi rimp,0x07 ; isolate channel number
ori rimp,cAdcV ; Set the voltage Ref bits
out ADMUX,rimp ; Set next MUX channel
out SREG,rSreg ; Restore SREG
reti
;
TC1CmpAIsrO: ; odd channel
mov rimp,rChCL ; copy channel counter
andi rimp,0xF8 ; isolate all but channel info
brne TC1CmpAIsrO1 ; no start condition
; TC1 has finished 32 cycles, starts new
in rimp,ADCL ; read ADC LSB
std Y+8,rimp ; store in Sram
in rimp,ADCH ; read ADC MSB
std Y+9,rimp ; store in Sram
rjmp TC1CmpAIsrO3
TC1CmpAIsrO1: ; not starting new
cpi rimp,0xF8 ; last measurement in channel?
breq TC1CmpAIsrO2 ; yes, add the last
; normal measurement, add to sum
in rimp1,ADCL ; read result LSB
ldd rimp,Y+8 ; read last sum
add rimp,rimp1 ; add new result
std Y+8,rimp ; store in Sram
in rimp1,ADCH ; read result MSB
ldd rimp,Y+9 ; read last sum MSB
adc rimp,rimp1 ; add to sum
std Y+9,rimp ; store in Sram
rjmp TC1CmpAIsrO3
TC1CmpAIsrO2: ; the last measurement of the series
in rimp1,ADCL ; read result
ldd rimp,Y+8 ; read last result
add rimp,rimp1 ; add to result
std Y+24,rimp ; store in sum Sram
in rimp1,ADCH ; read result MSB
ldd rimp,Y+9 ; load sum result MSB
adc rimp,rimp1 ; add MSB to result
std Y+25,rimp ; store in sum Sram MSB
TC1CmpAIsrO3:
adiw YL,2 ; next position in Sram
adiw rChCL,1 ; next channel
mov rimp,rChCL ; copy LSB counter
andi rimp,0x07 ; isolate channel number
brne TC1CmpAIsrO4 ; not channel 0
ldi YH,HIGH(sAdcE1) ; pointer to start
ldi YL,LOW(sAdcE1)
TC1CmpAIsrO4:
ori rimp,cAdcV ; Set the Ref bits to the selected voltage
out ADMUX,rimp ; Set next MUX channel
tst rChCL ; All new?
brne TC1CmpAIsrO5
sbr rFlg,1<<b32m ; set flag for 32 cycles
TC1CmpAIsrO5:
out SREG,rSreg ; Restore SREG
reti
;
; TC1 Compare B Int Service Routine
;
TC1CmpBIsr:
sbi ADCSR,ADSC ; start ADC
reti
;
; TC0 Overflow Int Service Routine
;
Tc0OvfIsr:
in rsreg,SREG ; Save SREG
inc rPwmC ; inc counter
brne Tc0OvfIsr1
mov rimp,rPwmOut ; Copy the current output
andi rimp,0xF0 ; Preserve the upper bits
mov rPwmOut,rimp ; write back
ldi rimp,0xF0 ; set all upper bits
eor rimp,rPwmOut ; Invert the upper bits
swap rimp ; upper to lower bits
or rPwmOut,rimp
TC0OvfIsr1:
cp rPwmC,rPwm1S
brne TC0OvfIsr2
cbr rPwmOut,1 ; Clear bit for Channel 1
TC0OvfIsr2:
cp rPwmC,rPwm2S
brne TC0OvfIsr3
cbr rPwmOut,2 ; Clear bit for Channel 2
TC0OvfIsr3:
cp rPwmC,rPwm3S
brne TC0OvfIsr4
cbr rPwmOut,4 ; Clear bit for Channel 3
TC0OvfIsr4:
cp rPwmC,rPwm4s
brne TC0OvfIsr5
cbr rPwmOut,8 ; Clear bit for Channel 4
TC0OvfIsr5:
out PORTC,rPwmOut ; To Port C
out SREG,rsreg ; Restore SREG
reti
;
; Uart RxC Interrupt Service Routine
;
SioRxCIsr:
in rSreg,SREG ; Save SReg
in rimp,UCSRA ; Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; isolate error bits
in rimp,UDR ; read character from UART
breq SioRxCIsr1 ; no errors
ldi rimp,'*' ; signal an error
sbrs rFlg,bUartRxLine ; Line buffer blocked?
out UDR,rimp
rjmp SioRxCIsr4 ; return from int
SioRxCIsr1:
sbrc rFlg,bUartRxLine ; Line buffer blocked?
rjmp SioRxCIsr4 ; yes, ignore character
out UDR,rimp ; echo the character
push ZH ; Save Z register
push ZL
ldi ZH,HIGH(sUartRxBs) ; Load Position for next RX char
lds ZL,sUartRxBp
st Z+,rimp ; save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; End of buffer?
brcc SioRxCIsr2 ; Buffer overflow
sts sUartRxBp,ZL ; Save next pointer position
SioRxCIsr2:
cpi rimp,cCr ; Carriage Return?
brne SioRxCIsr3 ; No, go on
ldi rimp,cLf ; Echo linefeed
out UDR,rimp
sbr rFlg,(1<<bUartRxLine) ; Set line complete flag
SioRxCIsr3:
pop ZL ; Restore Z-register
pop ZH
SioRxCIsr4:
out SREG,rSreg ; Restore SREG
reti ; Return from Int
;
;*************************** Main program *******************
;
; Main program start
;
main:
ldi rmp,HIGH(RAMEND) ; Set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; Init registers and ram locations
clr rFlg ; Clear all multi-purpose flags
clr rFlgD ; Clear the display flag
ldi rFlgD,0x0F ; enable Lcd line access as default
; Init ports
clr rmp ; Set port A bits all input
out DDRA,rmp
ldi rmp,0xFF ; Set PORTC all bits output
out DDRC,rmp
ldi rmp,0xF2 ; Set Port D Bits 7..4 and 1 to be output
out DDRD,rmp
; Init keys
rcall KeyInit ; Init the key routines
; Init the Leds
rcall KeyLedInit ; Init the Leds
; clear the state flags and system time
clr rmp
ldi ZH,HIGH(sState)
ldi ZL,LOW(sState)
st Z+,rmp ; sState
st Z+,rmp ; sTimeM
st Z+,rmp ; sTimeH
st Z+,rmp ; sTimeD
st Z+,rmp ; Lcd Cursor position
ldi ZH,HIGH(sAdcC) ; Init empty mAh-count
ldi ZL,LOW(sAdcC)
ldi rmp,16 ; locations to delete
clr R0
main1:
st Z+,R0
dec rmp
brne main1
ldi ZH,HIGH(sCh1UV) ; Init empty akku characteristics
ldi ZL,LOW(sCh1UV)
ldi rmp,32
main2:
st Z+,R0
dec rmp
brne main2
sts sUartCurCh,R0 ; clear Uart channel counter
; Init the Eeprom list of akkus
rcall EpInit
; Init the Uart
call UartInit ; Init UART receiver+transmitter
call UartSendOpenText ; Send the opening text
call UartSendCursor ; Send the cursor over Uart
; Init the LCD display
rcall LcdInit ; Init the LCD
; Init the PWM channels
clr rPwm1S ; Set startup value for Pwm Channel 0
clr rPwm2S
clr rPwm3S
clr rPwm4S
clr rPwmOut
; Init the timers 0 and 1
ldi rmp,HIGH(cTC1Div) ; TC1: Divider for 64 Hz signal
out OCR1AH,rmp ; MSB first!
ldi rmp,LOW(cTC1Div)
out OCR1AL,rmp ; LSB last!
ldi rmp,HIGH(cTC1CompB) ; MSB first!
out OCR1BH,rmp
ldi rmp,LOW(cTC1CompB) ; LSB last!
out OCR1BL,rmp
clr rmp ; TC1: no output pins, no pwm
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; TC1: CTC and Prescaler = 8
out TCCR1B,rmp
ldi rmp,(1<<TOIE0)|(1<<OCIE1A)|(1<<OCIE1B) ; TC0 overflow TC1 CompA/B int
out TIMSK,rmp
ldi rmp,1<<CS00 ; Set TC0 Prescaler divider to 1
out TCCR0,rmp
; Init the ADC
ldi YH,HIGH(sAdcE1) ; Y is ADC result pointer
ldi YL,LOW(sAdcE1)
clr rChCH ; Set channel counter for ADC to 0
clr rChCL
ldi rmp,cAdcV ; set ADC voltage, mux to channel 0
out ADMUX,rmp
ldi rmp,cStartAdc ; Enable ADC, prescale=128, disable int
out ADCSR,rmp
sei ; Enable Ints
loop:
; Don't use sleep modes here, it will disturb the ADC timing
tst rFlg ; any flag set?
breq loop ; no, go to loop again
ldi rmp,LOW(loop) ; Push return adress to stack
push rmp
ldi rmp,HIGH(loop)
push rmp
; check the 64 Hz tick from timer 0
sbrc rFlg,b64Hz ; a tick?
rjmp Tick64Hz ; read keys
; check if 32 measure cycles complete and 4 sec are over
sbrc rFlg,b32m ; Check 4 seconds over
rjmp Adc32m ; Jump to 32 measurements complete
; check if results are ready for Uart hex out
sbrc rFlgD,bURdy
rjmp DisplHex
; check if results are ready for LCD display
sbrc rFlgD,bLRdy
rjmp DisplLcd
; Check if a minute is over
sbrc rFlg,bMin ; minute over flag
rjmp Minute ; jump to the minute routine
; Check if a line from the Uart is complete
sbrs rFlg,bUartRxLine ; Check RX line complete
ret
jmp UartRxLine ; yes, answer
;
; 64 Hz Tick
;
Tick64Hz:
cbr rFlg,1<<b64Hz ; clear flag
rcall KeyLeds
rjmp Keys
;
; Include the calculation routines
;
.INCLUDE "akkucalc.asm"
;
; Include the key routines
;
.INCLUDE "akkukey.asm"
;
; Include the LCD-routines
;
.INCLUDE "akkulcd.asm"
;
; Include Uart-RX-routines
;
.INCLUDE "akkuuart.asm"
;
; End of code segment
;
; EEPROM segment, init my akkus
;
.ESEG
;
; Akku definition:
; Byte 1: number id, must be running from 1 in consecutive order
; Byte 2: size of the cell, A0(Mono), A1(Baby), A2(AA), A3(AAA)
; Byte 2 and 3: nominal capacity in mAh, LSB and MSB
; Byte 4 and 5: number of loads with nominal capacity, LSB and MSB
; Byte 6 and 7: capacity of loads, remaining mAh from last charge
; Byte 8 to 16: text description of the cell, exactly 8 chars
;
; Akku 1: AAA, NiMH, Conrad 250185
.DB 0x01,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 2: AAA, NiMH, Conrad 250185
.DB 0x02,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 3: AAA, NiMH, Conrad 250185
.DB 0x03,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 4: AAA, NiMH, Conrad 250185
.DB 0x04,0xA3
.DW 500,4,0
.DB "ConradMH"
;
; Akku 5: AA, NiMH, Pixcell Camera
.DB 0x05,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 6: AA, NiMH, Pixcell Camera
.DB 0x06,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 7: AA, NiMH, Pixcell Camera
.DB 0x07,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 8: AA, NiMH, Pixcell Camera
.DB 0x08,0xA2
.DW 1800,10,0
.DB "PixcelMH"
;
; Akku 9: AA, NiMH, Conrad Voltcraft
.DB 0x09,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 10: AA, NiMH, Conrad Voltcraft
.DB 0x0A,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 11: AA, NiMH, Conrad Voltcraft
.DB 0x0B,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; Akku 12: AA, NiMH, Conrad Voltcraft
.DB 0x0C,0xA2
.DW 1700,6,0
.DB "VoltcrMH"
;
; End of accumulator definitions
;

http://www.avr-asm-tutorial.net/akkuload/en/akkuload.asm1/20/2009 7:51:11 PM
http://www.avr-asm-tutorial.net/akkuload/en/akkucalc.asm

; ******************************************************************
; * Include routine for akkuload, calculation and display routines *
; * (C)2005 by Gerh.Schmidt, info@avr-asm-tutorial.net *
; ******************************************************************
;
; ************** EEPROM Init, Read and Write ******************
;
; Initialises the Eeprom storage of akkus
;
EpInit:
clr ZH ; Z is Eeprom read pointer
clr ZL
clr R0 ; R0 is counter
EpInit1:
sbic EECR,EEWE ; wait for write end
rjmp EpInit1 ; wait because write bit is set
inc R0 ; next akku
ldi rmp,cEepMax+1 ; check if beyond last id
cp R0,rmp ; compare with max number
brcc EpInit4
out EEARL,ZL ; set EEPROM read adress
out EEARH,ZH
sbi EECR,EERE ; set read enable
EpInit2:
sbic EECR,EERE ; wait for read ok
rjmp EpInit2 ; wait on
in rmp,EEDR ; read akku number
cp rmp,R0 ; compare with akku number
brne EpInit4 ; not correct, skip further read
adiw ZL,1 ; next byte
out EEARL,ZL ; set EEPROM read adress
out EEARH,ZH
sbi EECR,EERE ; set read enable
EpInit3:
sbic EECR,EERE ; wait for read ok
rjmp EpInit3 ; wait on
in rmp,EEDR ; read id byte
cpi rmp,0xA0 ; must be between A0 and A3
brcs EpInit4 ; smaller than A0, skip further read
cpi rmp,0xA4
brcc EpInit4 ; greater than A3, skip further read
adiw ZL,15 ; next EEPROM location
rjmp EpInit1
EpInit4:
dec R0 ; store number of akkus
sts sEaNm,R0
ret
;
; Read the Eeprom content of akku Id in rmp to the buffer
;
EpRead:
dec rmp ; starts with id=1
mov ZL,rmp ; copy to Z
clr ZH
lsl ZL ; *2
rol ZH
lsl ZL ; *4
rol ZH
lsl ZL ; *8
rol ZH
lsl ZL ; *16
rol ZH
ldi XH,HIGH(sEepB) ; X is buffer adress counter
ldi XL,LOW(sEepB)
EpRead1:
sbic EECR,EEWE ; wait for end of write, if necessary
rjmp EpRead1
out EEARH,ZH ; output read adress
out EEARL,ZL
sbi EECR,EERE ; set read enable
EpRead2:
sbic EECR,EERE ; wait for end of read
rjmp EpRead2
in rmp,EEDR ; read byte
st X+,rmp ; store in buffer
adiw ZL,1 ; next byte in EEPROM
mov rmp,ZL ; test for end
andi rmp,0x0F ; check last four bits clear
brne EpRead1 ; read another byte
ret
;
; Write the buffer content to the EEPROM
;
EpWrite:
ldi XH,HIGH(sEepB) ; X is buffer adress counter
ldi XL,LOW(sEepB)
ld rmp,X ; read id number
dec rmp ; starts with id=1
mov ZL,rmp ; copy to Z
clr ZH
lsl ZL ; *2
rol ZH
lsl ZL ; *4
rol ZH
lsl ZL ; *8
rol ZH
lsl ZL ; *16
rol ZH
EpWrite1:
sbic EECR,EEWE ; wait for end of write, if necessary
rjmp EpWrite1
out EEARH,ZH ; output write adress
out EEARL,ZL
ld rmp,X+ ; read byte from buffer
out EEDR,rmp ; write to data register
cli ; stop interrupts
sbi EECR,EEMWE ; set write mode enable
sbi EECR,EEWE ; set write enable
sei ; enable interrupts
adiw ZL,1 ; next byte in EEPROM
mov rmp,ZL ; test for end
andi rmp,0x0F ; check last four bits clear
brne EpWrite1 ; write another byte
ret
;
; Check Akku Id and add current to stored akku in Eeprom
; R0 is channel, preserves R0 and R1!
;
EpStore:
rcall GetAkkuId ; read id of the current channel
tst rmp ; id=0?
breq EpStore4 ; yes, return
lds ZL,sEANm ; read the number of id's in EEPROM
sec ; set carry
cpc rmp,ZL ; compare with (number of id's+1)
brcc EpStore4 ; greater than number of id's
rcall EpRead ; read the EEPROM id to buffer
ldi ZH,HIGH(sAdcC) ; point to measured capacity
ldi ZL,LOW(sAdcC)
add ZL,R0 ; add channel number
add ZL,R0
ld XL,Z+ ; read loaded capacity to X
ld XH,Z
lds ZL,sENRL ; read rest capacity from buffer to Z
lds ZH,sENRM
add ZL,XL ; add loaded capacity
adc ZH,XH
lds XL,sENCL ; read nominal capacity to X
lds XH,sENCM
clr rmp ; clear counter
EpStore1:
cp ZL,XL ; compare accumulated capacity in Z with nominal in X
cpc ZH,XH
brcs EpStore2 ; number of loads ready
sub ZL,XL ; subtract nominal capacity
sbc ZH,XH
inc rmp
rjmp EpStore1
EpStore2: ; number of loads is in rmp
sts sENRL,ZL ; store rest capacity in buffer
sts sENRM,ZH
tst rmp ; a full load?
breq EpStore3
lds ZL,sENLL ; read number of loads
add ZL,rmp
sts sENLL,ZL ; store number of loads
brcc EpStore3 ; no carry
lds ZL,sENLM ; inc MSB
inc ZL
sts sENLM,ZL
EpStore3: ; buffer is ready, write
rcall EpWrite ; write the buffer to EEPROM
EpStore4:
ret
;
; *** Convert measured voltages to decimal voltages and currents ***
;
; Convert ADC value of 32 cycles to binary voltage
; sd32e in R3:R2, result in R3:R2, uses R6:R5:R4
; Reference voltage is 5V, U[mV] = s32 * 39 / 256
;
Adc2mV:
mov R4,R2 ; copy s32 to R6:R5:R4
mov R5,R3
clr R6
lsl R4 ; * 2
rol R5
rol R6
lsl R4 ; * 4
rol R5
rol R6
lsl R4 ; * 8
rol R5
rol R6
mov R0,R4 ; copy to rmp:R1:R0
mov R1,R5
mov rmp,R6
lsl R4 ; * 16
rol R5
rol R6
lsl R4 ; * 32
rol R5
rol R6
add R4,R0 ; * 40
adc R5,R1
adc R6,rmp
clr rmp
sub R4,R2 ; * 39
sbc R5,R3
sbc R6,rmp
mov R2,R5 ; / 256
mov R3,R6
ldi rmp,0x80 ; round
add rmp,R4
clr rmp
adc R2,rmp
adc R3,rmp
ret
;
; Negative to positive/positive to negative
;
Negative:
neg R2 ; Two's complement
clr rmp
sbc rmp,R3
mov R3,rmp
ret
;
; Convert mV difference to mA
; mV in R3:R2, result in R3:R2
; Adc voltage reference is 5V
; mA = 11.84 * (s32odd - s32even) / 256
;
mV2mA:
ldi rmp,0x80 ; test negative
and rmp,R3
mov R0,rmp ; remember sign flag
breq mV2mA1 ; not negative
; convert negative to positive
rcall negative
mV2mA1:
mov R4,R2 ; copy to R6:R5:R4
mov R5,R3
clr R6
lsl R4 ; * 2
rol R5
rol R6
add R4,R2 ; * 3
adc R5,R3
clr rmp
adc R6,rmp
lsl R4 ; * 6
rol R5
rol R6
lsl R4 ; * 12
rol R5
rol R6
lsr R3 ; R3:R2 / 2
ror R2
lsr R3 ; R3:R2 / 4
ror R2
lsr R3 ; R3:R2 / 8
ror R2
sub R4,R2 ; * 11.88
sbc R5,R3
sbc R6,rmp
mV2mA3:
mov R2,R5 ; move the result to R3:R2, dividing by 256
mov R3,R6
ldi rmp,0x80 ; round result
add rmp,R4
clr rmp
adc R2,rmp
adc R3,rmp
tst R0 ; check negative
breq mV2mA4
rjmp negative
mV2mA4:
ret
;
; Convert mA to mAh
; Input: R6:R5:R4 has the current as 256*I
; output: R3:R2 has the mAh as 256*mAh
;
mA2mAh:
mov R1,R4 ; copy the current to R3:R2:R1
mov R2,R5
mov R3,R6
lsr R3 ; divide the current by 2
ror R2
ror R1
lsr R3 ; divide the current by 4
ror R2
ror R1
; The current in mA, multiplied by 64, is now in R3:R2:R1
clr rmp
add R1,R5 ; add the original current to yield 65 * I
adc R2,R6
adc R3,rmp
; The current in mA, multiplied by 65, is now in R3:R2:R1
lsl R4 ; now multiply the original current by 8
rol R5
rol R6
lsl R4 ; * 4
rol R5
rol R6
lsl R4 ; * 8
rol R5
rol R6
clr rmp ; round this up
rol R4 ; upmost bit into carry
adc R5,rmp
adc R6,rmp
add R1,R5 ; now at 8*I to 65*I to get 73*I
adc R2,R6
adc R3,rmp
; The result of 73*I/256 is now in R3:R2
; This number is equal to the mAh, multiplied by 256,
; that were stored in the accu in the last 4 seconds
ret
;
; ********* 32 Measurement of voltages are completed *******
;
; ADC completed 32 measurements
;
Adc32m:
cbr rFlg,1<<b32m ; clear 4s flag
mov rmp,rChCH ; check MSB timer
andi rmp,0x0F ; check lower nibble if 15 has been reached
cpi rmp,15
brcs Adc32m1 ; no, go on
sbr rFlg,1<<bMin ; set minute flag
ldi rmp,1 ; correct lower nibble
add rChCH,rmp
mov rmp,rChCH ; check upper nibble
andi rmp,0xF0 ; 15 minutes reached?
cpi rmp,0xF0 ; upper nibble = 15?
brne Adc32m1 ; no, jump
ldi rmp,0x10 ; correct MSB
add rChCH,rmp
; 15 minutes are over here
Adc32m1: ; calculate all voltages
ldi ZH,HIGH(sAdcE4); Z points to measured values
ldi ZL,LOW(sAdcE4)
Adc32m2:
ld R2,Z ; copy the measured value to R3:R2
ldd R3,Z+1
rcall Adc2mV ; convert to mV
std Z+16,R2 ; store in SRam
std Z+17,R3
adiw ZL,2
cpi ZL,LOW(sAdcE4+16) ; end reached?
brcs Adc32m2
; calculate all currents and loaded capacities
ldi ZH,HIGH(sAdcE4) ; Z points to measured values
ldi ZL,LOW(sAdcE4)
Adc32m3:
ld R0,Z ; Load even measure sum LSB to R0
ldd R1,Z+1 ; dto., MSB to R1
ldd R2,Z+8 ; Load odd measure LSB to R2
ldd R3,Z+9 ; dto., MSB
sub R2,R0 ; subtract LSB
sbc R3,R1 ; dto., MSB
rcall mV2mA ; calculate current
std Z+32,R2 ; store current in Sram, LSB
std Z+33,R3 ; dto., MSB
rcall mA2mAh ; calculate the mAh from the mA
ldd rmp,Z+48 ; read LLSB of capacity to rmp
ldd R0,Z+40 ; read LSB to R0
ldd R1,Z+41 ; read MSB to R1
add rmp,R2 ; add LLSB
adc R0,R3 ; add LSB
clr R3 ; add MSB
adc R1,R3
std Z+48,rmp ; store LLSB in Sram
std Z+40,R0 ; store LSB in Sram
std Z+41,R1 ; store MSB in Sram
adiw ZL,2
cpi ZL,LOW(sAdcE4+8) ; at end?
brcs Adc32m3 ; again until four times
sbr rFlgD,(1<<bURdy)|(1<<bLRdy) ; set result ready flags
ret
;
; *********** Check current channel states and change them ******
;
; add channel in R0 as displacement to address in Z
;
ChAdrs:
mov rmp,R0 ; channel to rmp
lsl rmp ; * 2
lsl rmp ; * 4
lsl rmp ; * 8
add ZL,rmp ; to correct address
ret
;
; Returns the akku id of the current channel in R0 in rmp
;
GetAkkuId:
ldi ZH,HIGH(sAdcAI1) ; Z is adress of the channel
ldi ZL,LOW(sAdcAI1)
add ZL,R0 ; add channel number
add ZL,R0
ld rmp,Z ; read channel id
ret
;
; Set the parameters for the selected accu id
; Expects channel in R0
;
IdSetPar:
rcall GetAkkuId ; read the accu id in the channel
tst rmp ; = Null?
breq IdSetPar1
lds R1,sEANm ; read number of accu id's
sec
cpc rmp,R1 ; compare with max number
brcc IdSetPar1
rcall EpRead ; read the accu info into buffer
lds R2,sENCL ; read capacity, LSB
lds R3,sENCM ; dto., MSB
ldi ZH,HIGH(sCh1UV) ; point Z to channel values
ldi ZL,LOW(sCh1UV)
rcall ChAdrs
ldi rmp,LOW(cUnlVol) ; set unload voltage to default
st Z+,rmp
ldi rmp,HIGH(cUnlVol)
st Z+,rmp
mov R4,R2 ; calculate load current
mov R5,R3
lsr R5
ror R4
lsr R5
ror R4
lsr R5
ror R4
st Z+,R4 ; store load current
st Z+,R5
add R2,R4 ; calculate load capacity
adc R3,R5
st Z+,R2 ; store load capacity
st Z+,R3
lsl R2 ; calculate maintain current
rol R3
st Z+,R3
clr rmp
st Z+,rmp
IdSetPar1:
ret
;
; Pwm address of current channel to Z
;
PwmAdrs:
ldi ZH,HIGH(cPwm1S) ; inactive channel
ldi ZL,LOW(cPwm1S)
add ZL,R0 ; address of channel
ret
;
; Set pwm value for channel in R0 to rmp, clear unload bit of channel
;
PwmSet:
ldi ZL,0xEF ; channel unload bit for channel 0
mov ZH,R0 ; copy channel number
PwmSet1:
tst ZH ; ok?
breq PwmSet2 ; yes
sec ; set carry to roll in
rol ZL ; next higher bit
dec ZH ; dec channel number
rjmp PwmSet1 ; again
PwmSet2:
and rPwmOut,ZL ; clear unload bit of channel
rcall PwmAdrs ; Pwm address of current channel to Z
st Z,rmp ; set pwm value for channel
ret
;
; Set channel (in R0) state to value in rmp
;
ChSet:
ldi ZL,0xFC ; channel mask bits
mov ZH,R0 ; copy channel number
ChSet1:
tst ZH ; channel reached?
breq ChSet2 ; yes
sec ; set carry for mask rol
rol ZL ; next channel
rol ZL
lsl rmp ; shift rmp left
lsl rmp
dec ZH ; next channel
rjmp ChSet1 ; again
ChSet2:
lds ZH,sState ; load state bits
and ZH,ZL ; clear channel activity bits
or ZH,rmp ; set desired activity bits for channel
sts sState,ZH ; set new state
ret
;
; Switch channel in R0 (from Unload) to Load
;
ToLoad:
ldi rmp,0x02 ; set channel mask to loading
rcall ChSet ; set state
ldi rmp,150 ; set pwm to medium voltage
rcall PwmSet
rjmp ClearCap ; clear capacity of channel
;
; Clear the capacity of the channel in R0
;
ClearCap:
ldi ZH,HIGH(sAdcC) ; point to loaded capacity
ldi ZL,LOW(sAdcC)
add ZL,R0
add ZL,R0
clr rmp
std Z+8,rmp ; clear LLSB
st Z+,rmp ; clear LSB
st Z,rmp
ret
;
; Compare current in the channel and correct, if necessary
; Expects channel in R0, pointer to the desired current in Z
;
ChCurrent: ; Check current too high or too small and correct
rcall ChAdrs ; correct address in Z to point to desired
ld R2,Z+ ; load desired current to R3:R2
ld R3,Z
ldi ZH,HIGH(sAdcI) ; point Z to measured current
ldi ZL,LOW(sAdcI)
add ZL,R0 ; to correct channel
add ZL,R0
ld R4,Z+ ; copy load current to R5:R4
ld R5,Z
sub R4,R2 ; subtract from desired current
sbc R5,R3
breq ChCurrent3 ; current is correct
brcs ChCurrent1 ; current is too small, increase
rcall PwmAdrs ; current too high, decrease
ld rmp,Z ; read pwm value
dec rmp
brne ChCurrent2
inc rmp
rjmp ChCurrent2
ChCurrent1:
rcall PwmAdrs
ld rmp,Z ; read pwm value
inc rmp ; increase
brne ChCurrent2
dec rmp
ChCurrent2:
st Z,rmp ; set new pwm value
ChCurrent3:
ret
;
; Check the states of the channels and change, if conditions are met
;
ChckStates:
clr R0 ; channel 0
lds R1,sState ; read the states
ChckStates1:
mov rmp,R1 ; copy state of channel
andi rmp,0x03
cpi rmp,1 ; state = 0?
brcc ChckStates2 ; state = 1 or higher
clr rmp ; set inactive channel
rcall PwmSet
rjmp ChckStates6
ChckStates2:
brne ChckStates3 ; state=2 or higher
ldi ZH,HIGH(sCh1UV) ; Unloading, point Z to threshold voltage
ldi ZL,LOW(sCh1UV)
rcall ChAdrs
ld R2,Z+ ; threshold voltage to R3:R2
ld R3,Z
ldi ZH,HIGH(sAdcU) ; last measured voltage
ldi ZL,LOW(sAdcU)
add ZL,R0 ; address of channel
add ZL,R0
ld R4,Z+ ; measured voltage to R4:R5
ld R5,Z
sub R4,R2 ; measured voltage > threshold voltage?
sbc R5,R3
brcc ChckStates6 ; no, go on
rcall ToLoad
rjmp ChckStates6
ChckStates3: ; state is 2 or higher
cpi rmp,2 ; is channel loading?
brne ChckStates5
ldi ZH,HIGH(sCh1LW) ; point to max. work
ldi ZL,LOW(sCh1LW)
rcall ChAdrs ; calculate channel adress
ld R2,Z+ ; max work to R3:R2
ld R3,Z
ldi ZH,HIGH(sAdcC) ; Z to selected capacity
ldi ZL,LOW(sAdcC)
add ZL,R0 ; correct channel address
add ZL,R0
ld R4,Z+ ; current work to R4:R3
ld R5,Z
sub R4,R2 ; capacity reached?
sbc R5,R3
brcs ChckStates4 ; no, go on loading
ldi rmp,0x03 ; set maintain state
rcall ChSet
ldi rmp,100 ; set pwm small
rcall PwmSet
rcall EpStore ; add capacity to the stored akku
rjmp ChckStates6
ChckStates4:
ldi ZH,HIGH(sCh1LC) ; point Z to load current
ldi ZL,LOW(sCh1LC)
rcall ChCurrent ; correct current to that value
rjmp ChckStates6
ChckStates5: ; channel is maintained
ldi ZH,HIGH(sCh1MC) ; maintain current
ldi ZL,LOW(sCh1MC)
rcall ChCurrent ; correct current to that value
ChckStates6:
lsr R1 ; channel mask next channel
lsr R1
inc R0 ; next channel
mov rmp,R0 ; channel = 5?
cpi rmp,5
brcc ChckStates7 ; yes, stop
rjmp ChckStates1 ; go on
ChckStates7:
ret
;
; Display result in hex on Uart
;
DisplHex:
cbr rFlgD,1<<bURdy ; clear display flag
rcall ChckStates ; check the states of the channels
sbrs rFlgD,bUHex ; is the display flag set?
ret ; jump over display outout in hex
ldi ZH,HIGH(sAdcE4) ; display results hex
ldi ZL,LOW(sAdcE4)
rjmp UartHex16 ; write the raw results of the measurements
;
; Display all voltages in Line 1 of the LCD
;
DispVtg:
ldi rmp,0 ; Lcd to line 1
rcall LcdLine
ldi XH,HIGH(sAdcU) ; X as pointer to values
ldi XL,LOW(sAdcU)
ldi rmp,'U'
DispVtg1:
rcall LcdChar
ld R2,X+ ; read value, LSB
ld R3,X+ ; dto., MSB
ldi rmp,LOW(10000) ; cannot exceed 10,000 mV
cp R2,rmp ; too high?
ldi rmp,HIGH(10000)
cpc R3,rmp
brcs DispVtg2
ldi rmp,'E' ; too big
rcall LcdChar
rcall LcdR0
rcall LcdR0
rcall LcdR0
rjmp DispVtg3
DispVtg2:
clr R0 ; suppress leading zeros
rcall LcdDec4
DispVtg3:
ldi rmp,' '
cpi XL,LOW(sAdcU+8) ; end reached?
brcs DispVtg1 ; again
ret
;
; Display currents on line 2
;
DispCurr:
ldi rmp,1 ; Lcd Line 2
rcall LcdLine ; set line
ldi XH,HIGH(sAdcI) ; point to currents
ldi XL,LOW(sAdcI)
ldi rmp,'I'
DispCurr1:
rcall LcdChar
ld R2,X+ ; read current, LSB
ld R3,X+ ; dto., MSB
mov rmp,R2 ; zero?
or rmp,R3
ldi rmp,' '
breq DispCurr2
mov rmp,R3 ; test if negative
rol rmp ; bit 7 of MSB
ldi rmp,'+' ; load +
brcc DispCurr2 ; not negative
rcall negative
ldi rmp,'-' ; load -
DispCurr2:
rcall LcdChar
clr R0 ; suppress leading zeros
rcall LcdDec3 ; display positive number
ldi rmp,' '
cpi XL,LOW(sAdcI+8) ; end?
brcs DispCurr1
ret
;
; Display mAh in Line 3
;
DispmAh:
ldi rmp,2 ; line 3
rcall LcdLine
ldi XH,HIGH(sAdcC) ; point X to mAh
ldi XL,LOW(sAdcC)
ldi rmp,'C'
DispmAh1:
rcall LcdChar ; write sign
ld R2,X+ ; read mAh LSB
ld R3,X+ ; read mAh MSB
mov rmp,R3 ; negative?
rol rmp ; sign to carry
brcc DispmAh2
rcall negative
DispmAh2:
clr R0 ; suppress leading zeros
rcall LcdDec4 ; write number to LCD
ldi rmp,' '
cpi XL,LOW(sAdcC+8) ; check end
brcs DispmAh1
ret
;
; Display result
;
DisplLcd:
cbr rFlgD,1<<bLRdy ; clear the display flag
sbrs rFlg,bLcdOk ; Jump over, if Lcd is ok
ret
sbrs rFlgD,bLcd3 ; Check if line 4 is accessible
rjmp DisplLcd1 ; jump over line 4 output
DisplLcd1:
sbrc rFlgD,bLcd0 ; check if line 1 is free for voltage
rcall DispVtg ; display voltages
sbrc rFlgD,bLcd1 ; check if line 2 is free for current
rcall DispCurr ; display current
sbrc rFlgD,bLcd2 ; check if line 3 is free for mAh
rcall DispmAh ; display mAh
rjmp LcdCursor
;
; Update system time
;
Time:
ldi ZH,HIGH(sTimeM)
ldi ZL,LOW(sTimeM)
ld rmp,Z ; add a minute
inc rmp
st Z,rmp
cpi rmp,60
brcs Time1
clr rmp ; new hour
st Z+,rmp
ld rmp,Z ; inc hours
inc rmp
st Z,rmp
cpi rmp,24
brcs Time1
clr rmp ; new day
st Z+,rmp
ld rmp,Z ; inc days
inc rmp
st Z,rmp
cpi rmp,100
brcs Time1
clr rmp
st Z,rmp
Time1:
ret
;
; Monitor results on the Uart
;
Monitor:
lds R1,sState ; read the status byte to R1
clr R5 ; channel counter
Monitor1:
mov rmp,R1
andi rmp,0x03 ; isolate activity bits
brne Monitor3
Monitor2:
lsr R1 ; next channel
lsr R1
inc R5
ldi rmp,4
cp R5,rmp
brcs Monitor1
ret
Monitor3: ; output the channel
ldi rmp,'1' ; send channel number
add rmp,R5
rcall UartSendChar
ldi rmp,':'
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'N'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi ZH,HIGH(sAdcAI1) ; point Z to Id
ldi ZL,LOW(sAdcAI1)
add ZL,R5
add ZL,R5
ld R2,Z
clr R3
rcall UartSendNmbr
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'S'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
mov rmp,R1
andi rmp,0x03
subi rmp,-'0'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcU) ; point Z to the measuring value
ldi ZL,LOW(sAdcU)
add ZL,R5
add ZL,R5
ld R2,Z+ ; read voltage
ld R3,Z+
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'V'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcI) ; point Z to current
ldi ZL,LOW(sAdcI)
add ZL,R5
add ZL,R5
ld R2,Z+
ld R3,Z
mov rmp,R3 ; negative cuurent?
rol rmp
brcc Monitor4
rcall Negative
ldi rmp,'-'
rcall UartSendChar
Monitor4:
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'A'
rcall UartSendChar
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi ZH,HIGH(sAdcC) ; point to work
ldi ZL,LOW(sAdcC)
add ZL,R5

http://www.avr-asm-tutorial.net/akkuload/en/akkucalc.asm (1 of 2)1/20/2009 7:51:16 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkucalc.asm

add ZL,R5
ld R2,Z+
ld R3,Z
rcall UartSendNmbr
ldi rmp,'m'
rcall UartSendChar
ldi rmp,'A'
rcall UartSendChar
ldi rmp,'h'
rcall UartSendChar
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp Monitor2
;
; Display time on LCD, if enabled
;
DisplTimeL:
sbrs rFlg,bLcdOk ; Check if Lcd is ok
ret
sbrs rFlgD,bLcd3 ; Check if line 4 is free
ret
ldi rmp,3 ; set Lcd to line 4
mov R1,rmp ; three numbers to display
rcall LcdLine ; Line 4
ldi XH,HIGH(sTimeD+1) ; display days
ldi XL,LOW(sTimeD+1)
DisplTimeL1:
ld R2,-X ; read number
clr R3 ; clear MSB
mov R0,R1 ; prevent suppressing leading zeros
rcall LcdDec2 ; output two digits
mov rmp,R1
cpi rmp,1 ; output : ?
breq DisplTimeL2 ; don't display :
ldi rmp,':' ; display :
rcall LcdChar
DisplTimeL2:
dec R1 ; all time info sent?
brne DisplTimeL1 ; no, again a number
ldi rmp,' '
rcall LcdChar
rjmp LcdCursor
;
; Display time over Uart
;
DispTimeU:
ldi rmp,cUartTime ; minutes per time display
mov R0,rmp
lds rmp,sTimeM ; read minutes
DispTimeU1:
tst rmp ; zero?
breq DispTimeUd
sub rmp,R0 ; subtract cUartTime
brcc DispTimeU1 ; no carry, check again
ret ; carry, don't display
;
; Displays time over Uart directly
;
DispTimeUd:
ldi rmp,'T' ; display time over Uart
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,3 ; three times
mov R1,rmp
ldi ZH,HIGH(sTimeD+1) ; point Z at Days
ldi ZL,LOW(sTimeD+1)
DispTimeUd1:
ld R2,-Z ; read a number
clr R3
mov R0,R1 ; don't suppress leading zeroes
rcall UartDec2
mov rmp,R1 ; check display :
cpi rmp,1
breq DispTimeUd2 ; don't display :
ldi rmp,':'
rcall UartSendChar
DispTimeUd2:
dec R1
brne DispTimeUd1 ; next number
ldi rmp,cCr ; Carriage return
rcall UartSendChar
ldi rmp,cLf ; Line feed
rjmp UartSendChar
;
; A minute is over, display results if flag is set
;
Minute:
cbr rFlg,1<<bMin ; clear the flag
rcall Time ; update system time
rcall DisplTimeL
sbrs rFlgD,bUMoni ; jump if monitor flag is on
ret ; nothing else to do
rcall DispTimeU ; display time over Uart
rjmp Monitor ; monitor results
;
; end of akkucalc include file
;

http://www.avr-asm-tutorial.net/akkuload/en/akkucalc.asm (2 of 2)1/20/2009 7:51:16 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkukey.asm

; **************************************************************
; * Include file for key routines for akkuloader.asm *
; * (C)2005 by Gerhard Schmidt, info@avr-asm-tutorial.net *
; **************************************************************
;
; Provides Registers Task
; ---------------------------------------------------------
; KeyInit rmp,Z,X Init the key input, set default values
; Keys rmp Asks the input pins for pressed keys,
; for main loop operation
; KeyMenueFirst nn Outputs the first menue for the keys
; ---------------------------------------------------------
;
; Constants
;
.EQU pLedO = PORTD ; Leds connected to port D
.EQU cLedM = 0xF0 ; All led port bits set
.EQU pKeyO = PORTD ; Keys connected to port D
.EQU pKeyD = DDRD ; Key direction registers
.EQU pKeyI = PIND ; Key read port
.EQU cKeyB = 0xE0 ; Three keys on bits 7, 6 and 5
.EQU cKeyM = 0x1F ; mask for clearing bits 7, 6, and 5
;
; ============== Routine for initialisation of the keys =====
;
; Init the Leds, powering the Leds on for 4 seconds
;
KeyLedInit:
ldi ZH,HIGH(sLedC)
ldi ZL,LOW(sLedC)
ldi rmp,5 ; 5 bytes
clr R0
KeyLedInit1:
st Z+,R0
dec rmp
brne KeyLedInit1
in rmp,pLedO
cbr rmp,cLedM ; clear the Led bit powering Leds on
out pLedO,rmp
ret
;
; Init the keys
;
KeyInit:
clr rKeyLst ; clear last key read
clr rKeyRep ; clear counter for key repeat
;
; Reset the variables for key inputs
;
KeyReset:
ldi XH,HIGH(sKeyJ1) ; target in Sram
ldi XL,LOW(sKeyJ1)
ldi ZH,HIGH(2*KeyInitTable) ; source table
ldi ZL,LOW(2*KeyInitTable)
ldi rmp,6 ; 3 words, 6 bytes
KeyReset1:
lpm ; read byte from table
adiw ZL,1
st X+,R0 ; to Sram
dec rmp
brne KeyReset1
clr rmp ; set channel = 0
sts sKeyCh,rmp
ret
;
; Table for key init
;
KeyInitTable:
.DW KeyM1,0,0
;
; ===================== Routines for the main loop ============
;
; operates the Led output
;
KeyLeds:
in R0,pLedO ; remember the actual output state
ldi rmp,0x0F ; clear all Led outputs, setting Leds on
and R0,rmp
lds rmp,sLedC ; read Led counter
dec rmp ; downcount counter
brne KeyLeds4 ; not zero, skip checking new states
lds R1,sState ; read status of the channels
ldi ZH,HIGH(sLed1) ; point Z to channel values
ldi ZL,LOW(sLed1)
ldi XL,4 ; repeat four times
KeyLeds1:
lsr R1 ; lower status bit
brcs KeyLeds2 ; lower status bit is one
ldi XH,32 ; channel compare value for 50% pulse width
lsr R1 ; higher status bit
brcs KeyLeds3 ; 10=load, set channel value
ldi XH,64 ; 00=inactive, later sets Led off
rjmp KeyLeds3 ; set channel value
KeyLeds2: ; lower status bit is one
clr XH ; 11=maintain, later sets Led on for whole cycle
lsr R1 ; shit higher bit to carry
brcs KeyLeds3 ; set channel value
ldi XH,56 ; 01=unload, sets Led on for 8 cycles
KeyLeds3: ; store channel value and repeat
st Z+,XH ; set channel value
dec XL ; next channel
brne KeyLeds1 ; another channel
ldi rmp,64 ; 64 cycles to counter
KeyLeds4: ; compare channels with counter in rmp
sts sLedC,rmp ; store counter
ldi XH,0x80 ; mask for setting a Led bit
ldi XL,4 ; four channels
ldi ZH,HIGH(sLed1) ; point Z to channel values
ldi ZL,LOW(sLed1)
KeyLeds5: ; check if Led should be off
ld R1,Z+ ; read channel value
cp R1,rmp ; compare counter and channel value
brcs KeyLeds6 ; leave Led output on
or R0,XH ; switch channel output on = Led Off
KeyLeds6:
lsr XH ; mask one right
dec XL ; next channel
brne KeyLeds5 ; again a channel
out pLedO,R0 ; set channel output bits
ret ; done
;
; Keys asks the input pins for pressed keys
;
Keys:
in R1,pKeyO ; Save current status of the output bits
in R0,pKeyD ; Save the direction bits
mov rmp,R0 ; copy direction bits
andi rmp,cKeyM ; clear the direction bits
out pKeyD,rmp ; set key pins to input
mov rmp,R1 ; set the pullup resistors on
ori rmp,cKeyB ; set bits to one
out pKeyO,rmp ; to port
nop ; wait a while
nop
nop
nop
in rmp,pKeyI ; read the key port
out pKeyD,R0 ; restore original directions
out pKeyO,R1 ; restore original output states
andi rmp,cKeyB ; isolate key bits
cpi rmp,cKeyB ; all keys inactive?
brne Keys2 ; no
Keys1:
clr rKeyRep ; repeat to zero
mov rKeyLst,rmp ; store this
ret ; done
Keys2:
cp rmp,rKeyLst ; equal to last key state?
brne Keys1 ; no, clear the counter
inc rKeyRep ; increase counter
ldi rmp,cKeyRep ; compare with preselected number
cp rmp,rKeyRep
breq Keys3 ; equal, go
ret
Keys3: ; Key ok, start selected routine
mov R0,rKeyLst ; read the keys again
ldi ZH,HIGH(sKeyJ1) ; point to first key adress
ldi ZL,LOW(sKeyJ1)
Keys4:
rol R0
brcc Keys5
adiw ZL,2 ; next adress
rjmp Keys4
Keys5:
ld rmp,Z+ ; read jump adress and jump
ld R0,Z
mov R1,R0 ; check if adress is zero
or R1,rmp
breq Keys6
push rmp
push R0
Keys6:
ret ; jump
;
; ================== common routines for menues ============
;
; Set position to Menue start
;
KeyMStrt:
push ZH ; save Z
push ZL
ldi ZH,3 ; line 4
ldi ZL,9 ; position 10
rcall LcdPos ; set position
pop ZL ; restore Z
pop ZH
ret
;
; clears the menue part and sets position
; to the beginning of this area
;
KeyMClr:
rcall KeyMStrt
ldi rmp,' '
mov R0,rmp
ldi rmp,11
mov R1,rmp
KeyMClr1:
rcall LcdR0
dec R1
brne KeyMClr1
rjmp KeyMStrt
;
; Display first menue on line 3
;
KeyMenueFirst:
rcall KeyMStrt ; set position
ldi ZH,HIGH(2*KeyTxtMenue)
ldi ZL,LOW(2*KeyTxtMenue)
rcall LcdDisplZ
ldi rmp,17 ; Set cursor position
sts sLcdCs,rmp
rjmp KeyReset ; init the jump adresses
; First menue on Lcd
KeyTxtMenue:
.DB " Menue...",0
;
; Output an error message on illegal channel numbers
;
KeyGetChError:
rcall KeyMClr ; Clear the menue part
ldi ZH,HIGH(2*KeyTxtChErr) ; Error text
ldi ZL,LOW(2*KeyTxtChErr)
rcall LcdDisplZ ; display error text
ldi rmp,18 ; set cursor position
sts sLcdCs,rmp
ret
;
; Get channel number in R0
; Display an error message if channel is not between 1..4, and return
; with carry flag set
;
KeyGetChR0:
lds R0,sKeyCh ; read current channel
tst R0 ; = zero?
breq KeyGetChR0e
push rmp
ldi rmp,5
cp R0,rmp ; > 4 ?
pop rmp
brcc KeyGetChR0e
clc
ret
KeyGetChR0e:
rcall KeyGetChError
sec
ret
;
KeyTxtChErr:
.DB "Ch error!",0
;
; Set selected channel state to value in rmp
;
KeyChSet:
rcall KeyGetChR0 ; get channel number in R0
brcs KeyChSet3
ldi ZL,0xFC ; channel mask bits = 0
KeyChSet1:
dec R0 ; channel reached?
breq KeyChSet2 ; yes
sec ; set carry for mask rol
rol ZL ; next channel
rol ZL
lsl rmp ; shift rmp left
lsl rmp
rjmp KeyChSet1 ; again
KeyChSet2:
lds ZH,sState ; load state bits
and ZH,ZL ; clear channel activity bits
or ZH,rmp ; set desired activity bits for channel
sts sState,ZH ; set new state
KeyChSet3:
ret
;
; Set the channel's pwm to the value in rmp
;
KeySetPwm:
rcall KeyGetChR0
brcs KeySetPwm2
ldi ZH,HIGH(cPwm1S-1) ; clear the channel's pwm value
ldi ZL,LOW(cPwm1S-1)
KeySetPwm1:
adiw ZL,1 ; next pwm channel
dec R0
brne KeySetPwm1
st Z,rmp ; set pwm value
KeySetPwm2:
ret
;
; Clear the channel's unload bit
;
KeyClrUnl:
rcall KeyGetChR0
brcs KeyClrUnl2
ldi rmp,0xF7 ; mask
KeyClrUnl1:
sec ; roll a 1 in
rol rmp ; rotate mask left
dec R0 ; next channel
brne KeyClrUnl1
and rPwmOut,rmp ; clear the unload bit
KeyClrUnl2:
ret ; done
;
; Clear the channel's capacity counter
;
KeyClrCap:
rcall KeyGetChR0
brcs KeyClrCap1
dec R0
ldi ZH,HIGH(sAdcC)
ldi ZL,LOW(sAdcC)
add ZL,R0
add ZL,R0
st Z+,rmp
st Z+,rmp
std Z+6,rmp
KeyClrCap1:
ret
;
; Get the parameter of the current channel, set adress and input decimal
; Expects the parameter base adress in X and the maximum in Z
;
KeyGetParam:
rcall KeyGetChR0
brcs KeyGetParam1
dec R0
lsl R0 ; * 8
lsl R0
lsl R0
add XL,R0 ; correct adress
clr R0
adc XH,R0
ld R0,X+ ; read LSB
sts sKeyNW,R0 ; store in decimal input number
ld R0,X ; read MSB
sts sKeyNW+1,R0
sts sKeyNM,ZL
sts sKeyNM+1,ZH
KeyGetParam1:
ret
;
; Set the parameter of the current channel
; Expects the parameter adress in X and the text message in Z
;
KeySetParam:
rcall KeyGetChR0
brcs KeySetParam1
dec R0
lsl R0 ; * 8
lsl R0
lsl R0
add XL,R0 ; correct adress
clr R0
adc XH,R0
lds rmp,sKeyNW
st X+,rmp
lds rmp,sKeyNW+1
st X,rmp
rcall KeyMClr
rcall LcdDisplZ
ldi ZH,HIGH(KeyM12a)
ldi ZL,LOW(KeyM12a)
ijmp
KeySetParam1:
ret
;
; After finishing a menue entry, display the text in X
;
KeyMDone:
rcall KeyMClr ; Clear the menue part of the LCD
rcall LcdDisplZ
mov ZH,XH
mov ZL,XL
ijmp
;
; ================= Handle menue table entries ===========
;
; Output the menue entry in X, menue entry in sKeyNC
; expects adress of menue table in X
;
KeyMOut:
rcall KeyMClr
KeyMOut1:
mov ZH,XH ; copy menue start to Z
mov ZL,XL
lds R1,sKeyNC ; read the entry number
KeyMOut2: ; check if current menue point reached
tst R1 ; menue point reached at zero?
brne KeyMOut5 ; not reached
KeyMOut3: ; reached, output text
lpm
adiw ZL,1
mov rmp,R0
cpi rmp,'#'
breq KeyMOut4
rcall LcdChar
rjmp KeyMout3
KeyMOut4: ; output finished, search next Null
lpm
adiw ZL,1
tst R0
brne KeyMOut4
; read the lcd position and the jump adress
lpm
adiw ZL,1
sts sLcdCs,R0
lpm
adiw ZL,1
sts sKeyJ3,R0 ; store adress in key 3
lpm
sts sKeyJ3+1,R0
ret
KeyMOut5: ; not the desired entry, search the next
lpm
adiw ZL,1
tst R0
brne KeyMOut5
adiw ZL,3
lpm
ldi rmp,0xFF
cp rmp,R0
breq KeyMOut6
dec R1
rjmp KeyMOut2
KeyMOut6: ; start new
clr R1
sts sKeyNC,R1
rjmp KeyMOut1
;
; ================= Get decimal number input ============
;
;
; Displays the decimal number in sKeyNW at the end of line 4
;
KeyDecDispl: ; display the decimal number
ldi ZH,3 ; Line 4
ldi ZL,15 ; Position 16
rcall LcdPos ; Set lcd position
lds R2,sKeyNW ; read number
lds R3,sKeyNW+1
rcall LcdDec5 ; write number on Lcd
lds ZL,sKeyNC ; set LCD cursor position
subi ZL,-15
sts sLcdCs,ZL
ldi ZH,3
rjmp LcdPos
;
; Set the decimal input jump adresses and get a decimal
; expects: text pointer in Z, return adress in X, skip adress
; in sKeyJ1
;
KeyDec:
rcall KeyMClr ; clear menue area
rcall LcdDisplZ ; output text
ldi ZH,HIGH(sKeyJR) ; point to return adress
ldi ZL,LOW(sKeyJR)
st Z+,XL
st Z+,XH
lds XL,sKeyJ1 ; store skip return adress
lds XH,sKeyJ1+1
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecL) ; J1 adress
ldi XH,HIGH(KeyDecL)
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecU) ; J2 adress
ldi XH,HIGH(KeyDecU)
st Z+,XL
st Z+,XH
ldi XL,LOW(KeyDecR) ; J3 adress
ldi XH,HIGH(KeyDecR)
st Z+,XL
st Z+,XH
ldi rmp,4 ; cursor at last digit
sts sKeyNC,rmp
rjmp KeyDecDispl ; display number and set cursor
;
KeyDecL: ; Left key
lds rmp,sKeyNC ; dec cursor position
dec rmp
cpi rmp,0xFF ; left out?
breq KeyDecL1
sts sKeyNC,rmp ; set cursor
rjmp KeyDecDispl ; display number and set cursor
KeyDecL1:
lds ZL,sKeyJS ; read skip adress
lds ZH,sKeyJS+1
ijmp ; jump to skip routine
;
KeyDecU: ; Middle key
ldi ZH,HIGH(2*KeyDecTbl) ; Z to decimal table
ldi ZL,LOW(2*KeyDecTbl)
lds rmp,sKeyNC ; add current position
lsl rmp ; * 2
add ZL,rmp ; point to value in decimal table
clr rmp
adc ZH,rmp
lpm ; read decimal value
mov XL,R0
adiw ZL,1
lpm
mov XH,R0
lds ZL,sKeyNW ; read current decimal number
lds ZH,sKeyNW+1
add ZL,XL ; add both
adc ZH,XH
lds XL,sKeyNM ; read maximum
lds XH,sKeyNM+1
sec
cpc ZL,XL ; compare with maximum
cpc ZH,XH
brcs KeyDecU1
clr ZH ; > max, clear number
clr ZL
KeyDecU1:
sts sKeyNW,ZL ; store number
sts sKeyNW+1,ZH
rjmp KeyDecDispl ; display number and set cursor
;
KeyDecR: ; Right key
lds rmp,sKeyNC ; read cursor
inc rmp ; next position
cpi rmp,5 ; right out?
brcc KeyDecR1 ; yes
sts sKeyNC,rmp ; store position
rjmp KeyDecDispl
KeyDecR1:
lds ZL,sKeyJR ; read jump adress
lds ZH,sKeyJR+1
ijmp ; jump to finish input
;
KeyDecTbl:
.DW 10000
.DW 1000
.DW 100
.DW 10
.DW 1
;
; ================= Menues =====================
;
; Menue 1, select
;
KeyM1:
ldi XH,HIGH(2*KeyTxtM1) ; Menue text
ldi XL,LOW(2*KeyTxtM1)
rcall KeyMOut ; Display menue part
KeyM1a:
ldi rmp,LOW(KeyMenueFirst) ; Set left key jump adress
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyMenueFirst)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM1Up) ; Set middle key jump adress
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM1Up)
sts sKeyJ2+1,rmp
clr rmp ; start with menue entry 0
sts sKeyNC,rmp
ret
;
; Menue 1 Up Routine
;
KeyM1Up:
lds rmp,sKeyNC ; next higher menue entry
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM1) ; point X at menue table
ldi XL,LOW(2*KeyTxtM1)
rjmp KeyMOut
;
; Menue 11: Select Akku and Channel
;
KeyM11:
clr rmp ; Set selected menue entry to 0
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM11) ; point X to menue table
ldi XL,LOW(2*KeyTxtM11)
rcall KeyMOut ; Display selected menue entry
KeyM11a:
ldi rmp,LOW(KeyM1) ; Set left key jump adress to menue 1
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM11Up) ; Set middle key jump adress to M11Up
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM11Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 11 Up key routine
;
KeyM11Up:
lds rmp,sKeyNC ; next menue entry
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM11) ; selected menue text
ldi XL,LOW(2*KeyTxtM11)
rjmp KeyMOut ; output menue entry
;
; Select Menue routines
;
KeyM111: ; Select akku number
rcall KeyGetChR0 ; read channel
brcs KeyM111e
dec R0
ldi ZH,HIGH(sAdcAI1) ; read akkunumber
ldi ZL,LOW(sAdcAI1)
add ZL,R0
add ZL,R0
ld rmp,Z
sts sKeyNW,rmp
clr rmp
sts sKeyNW+1,rmp
lds rmp,sEANm ; read number of akkus
sts sKeyNM,rmp ; set max akkus
clr rmp
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM111R) ; Return adress in X
ldi XL,LOW(KeyM111R)
ldi ZH,HIGH(2*KeyTxtM111) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM111)
rjmp KeyDec ; input a decimal number
KeyM111e:
ret
;
KeyTxtM111:
.DB "Akku=",0
;
; Return from dec input with akku number
;
KeyM111R:
rcall KeyGetChR0
brcs KeyM111Re
dec R0
ldi ZH,HIGH(sAdcAI1)
ldi ZL,LOW(sAdcAI1)
add ZL,R0
add ZL,R0
lds rmp,sKeyNW ; copy input number to channel
st Z,rmp
rcall IdSetPar
ldi XH,HIGH(KeyM11a) ; jump back
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt112R)
ldi ZL,LOW(2*KeyTxt112R)
rjmp KeyMDone
KeyM111Re:
ret
;
KeyTxt111R:
.DB "Accu set",0,0
;
KeyM112: ; Select channel number
lds rmp,sKeyCh ; read channel and transfer to number input
sts sKeyNW,rmp
clr rmp
sts sKeyNW+1,rmp
ldi rmp,4 ; Set maximum value
sts sKeyNM,rmp
clr rmp
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM112R) ; Return adress in X
ldi XL,LOW(KeyM112R)
ldi ZH,HIGH(2*KeyTxtM112) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM112)
rjmp KeyDec ; input a decimal number
;
KeyTxtM112:
.DB "Chann=",0,0
;
; Set channel to input number
;
KeyM112R:
lds rmp,sKeyNW ; copy input number to channel
sts sKeyCh,rmp
ldi XH,HIGH(KeyM11a) ; jump back
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt112R)
ldi ZL,LOW(2*KeyTxt112R)
rjmp KeyMDone
;
KeyTxt112R:
.DB "Ch set",0,0
;
KeyM113: ; Direct load
ldi rmp,LOW(500)
sts sKeyNW,rmp
ldi rmp,HIGH(500)
sts sKeyNW+1,rmp
ldi rmp,LOW(9999)
sts sKeyNM,rmp
ldi rmp,HIGH(9999)
sts sKeyNM+1,rmp
ldi XH,HIGH(KeyM113R) ; Return adress in X
ldi XL,LOW(KeyM113R)
ldi ZH,HIGH(2*KeyTxtM113) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM113)
rjmp KeyDec ; input a decimal number
;
KeyTxtM113:
.DB "Capac.=",0
;
KeyM113R:
rcall KeyGetChR0
brcs KeyM113Re
rcall KeyClrUnl
ldi rmp,0x02 ; set load state
rcall KeyChSet
ldi rmp,128
rcall KeySetPwm
rcall KeyGetChR0
dec R0
lsl R0
lsl R0
lsl R0
ldi ZH,HIGH(sCh1LC) ; set current
ldi ZL,LOW(sCh1LC)
add ZL,R0
clr R0
adc ZH,R0
lds XL,sKeyNW ; read capacity
lds XH,sKeyNW+1
mov R2,XL ; copy
mov R3,XH
lsr R3 ; / 2
ror R2
lsr R3 ; / 4
ror R2
lsr R3 ; / 8
ror R2
st Z+,R2 ; set load current
st Z+,R3
add XL,R2 ; add to nominal capacity
adc XH,R3
st Z+,XL ; set capacity
st Z+,XH
lsl XL ; * 2
rol XH
clr rmp
rol rmp
st Z+,XH ; set maintain current
st Z,rmp
ldi XH,HIGH(KeyM11a) ; return adress
ldi XL,LOW(KeyM11a)
ldi ZH,HIGH(2*KeyTxt113D) ; text output
ldi ZL,LOW(2*KeyTxt113D)
rjmp KeyMDone
KeyM113Re:
ret
;
KeyTxt113D:
.DB "Autoload",0,0
;
; Menue "Set" routines
;
KeyM12:
clr rmp ; Set selected menue entry to 0
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM12) ; point X to menue table
ldi XL,LOW(2*KeyTxtM12)
rcall KeyMOut ; Display selected menue entry
KeyM12a:
ldi rmp,LOW(KeyM1) ; Set left key jump adress to menue 1
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM12Up) ; Set middle key jump adress to M12Up
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM12Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 12 Up key routine
;
KeyM12Up:
lds rmp,sKeyNC ; next menue entry
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM12) ; selected menue text
ldi XL,LOW(2*KeyTxtM12)
rjmp KeyMOut ; output menue entry
;
KeyM121:
ldi XH,HIGH(sCh1UV) ; channel number
ldi XL,LOW(sCh1UV)
ldi ZH,HIGH(1300) ; maximum
ldi ZL,LOW(1300)
rcall KeyGetParam ; Parameter in X to input and maximum to Z
ldi XH,HIGH(KeyM121R) ; Return adress in X
ldi XL,LOW(KeyM121R)
ldi ZH,HIGH(2*KeyTxtM121) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM121)
rjmp KeyDec; input a decimal number
;
KeyM122:
ldi XH,HIGH(sCh1LC) ; channel number
ldi XL,LOW(sCh1LC)
ldi ZH,HIGH(350) ; maximum
ldi ZL,LOW(350)
rcall KeyGetParam ; Parameter in X to input and maximum to Z
ldi XH,HIGH(KeyM122R) ; Return adress in X
ldi XL,LOW(KeyM122R)
ldi ZH,HIGH(2*KeyTxtM122) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM122)
rjmp KeyDec; input a decimal number
;
KeyM123:
ldi XH,HIGH(sCh1LW) ; channel number
ldi XL,LOW(sCh1LW)
ldi ZH,HIGH(9999) ; maximum
ldi ZL,LOW(9999)
rcall KeyGetParam ; Parameter in X to input and maximum to Z
ldi XH,HIGH(KeyM123R) ; Return adress in X
ldi XL,LOW(KeyM123R)
ldi ZH,HIGH(2*KeyTxtM123) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM123)
rjmp KeyDec; input a decimal number
;
KeyM124:
ldi XH,HIGH(sCh1MC) ; channel number
ldi XL,LOW(sCh1MC)
ldi ZH,HIGH(100) ; maximum
ldi ZL,LOW(100)
rcall KeyGetParam ; Parameter in X to input and maximum to Z
ldi XH,HIGH(KeyM124R) ; Return adress in X
ldi XL,LOW(KeyM124R)
ldi ZH,HIGH(2*KeyTxtM124) ; Text adress in Z
ldi ZL,LOW(2*KeyTxtM124)
rjmp KeyDec; input a decimal number
;
KeyTxtM121:
.DB "Unload=",0
;
KeyTxtM122:
.DB "Load I=",0
;
KeyTxtM123:
.DB "Capac.=",0
;
KeyTxtM124:
.DB "Maint.=",0
;
; Set the channels unload voltage to the value in sKeyNW
;
KeyM121R:
ldi XH,HIGH(sCh1UV) ; X to unload voltage
ldi XL,LOW(sCh1UV)
ldi ZH,HIGH(2*KeyTxtM121D) ; Z to text
ldi ZL,LOW(2*KeyTxtM121D)
rjmp KeySetParam ; set the channel's parameter
;

http://www.avr-asm-tutorial.net/akkuload/en/akkukey.asm (1 of 2)1/20/2009 7:51:20 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkukey.asm

; Set the channels load current to the value in sKeyNW


;
KeyM122R:
ldi XH,HIGH(sCh1LC) ; X to load current
ldi XL,LOW(sCh1LC)
ldi ZH,HIGH(2*KeyTxtM122D) ; Z to text
ldi ZL,LOW(2*KeyTxtM122D)
rjmp KeySetParam ; set the channel's parameter
;
; Set the channels nominal capacity to the value in sKeyNW
;
KeyM123R:
ldi XH,HIGH(sCh1LW) ; X to capacity
ldi XL,LOW(sCh1LW)
ldi ZH,HIGH(2*KeyTxtM123D) ; Z to text
ldi ZL,LOW(2*KeyTxtM123D)
rjmp KeySetParam ; set the channel's parameter
;
; Set the channels maintain current to the value in sKeyNW
;
KeyM124R:
ldi XH,HIGH(sCh1MC) ; X to maintain current
ldi XL,LOW(sCh1MC)
ldi ZH,HIGH(2*KeyTxtM124D) ; Z to text
ldi ZL,LOW(2*KeyTxtM124D)
rjmp KeySetParam ; set the channel's parameter
;
KeyTxtM121D:
.DB "Unload set",0,0
;
KeyTxtM122D:
.DB "Load set",0,0
;
KeyTxtM123D:
.DB "Capac. set",0,0
;
KeyTxtM124D:
.DB "Maint. set",0,0
;
;.EQU sKeyNC = $00ED ; Decimal number input position
;.EQU sKeyNW = $00EE ; Decimal number in and output word
;.EQU sKeyNM = $00F0 ; Decimal number maximum value
;.EQU sKeyJR = $00F2 ; Jump adress on number input ready
;.EQU sKeyJS = $00F4 ; Jump adress on skip number input
;.EQU sKeyJ1 = $00F6 ; Jump adress on key 1
;.EQU sKeyJ2 = $00F8 ; dto., key 2
;.EQU sKeyJ3 = $00FA ; dto., key 3
;
; Select a command
;
KeyM13:
clr rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM13) ; Menue text
ldi XL,LOW(2*KeyTxtM13)
rcall KeyMOut ; Display menue part
KeyM13a:
ldi rmp,LOW(KeyM1) ; Set left key jump adress
sts sKeyJ1,rmp
ldi rmp,HIGH(KeyM1)
sts sKeyJ1+1,rmp
ldi rmp,LOW(KeyM13Up) ; Set middle key jump adress
sts sKeyJ2,rmp
ldi rmp,HIGH(KeyM13Up)
sts sKeyJ2+1,rmp
ret
;
; Menue 13 Up key routine
;
KeyM13Up:
lds rmp,sKeyNC
inc rmp
sts sKeyNC,rmp
ldi XH,HIGH(2*KeyTxtM13) ; Menue text
ldi XL,LOW(2*KeyTxtM13)
rjmp KeyMOut
;
; Command Menues, sets sState of the selected channel in sKeyCh
;
KeyM131: ; set sState to unload
ldi rmp,0x01
rcall KeyChSet
clr rmp
rcall KeySetPwm
rcall KeyClrCap
ldi rmp,0x08 ; set the channel's unload bit
lds R0,sKeyCh
KeyM131b:
lsl rmp
dec R0
brne KeyM131b
or rPwmOut,rmp ; set the channel's unload bit
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM131D)
ldi ZL,LOW(2*KeyTxtM131D)
rjmp KeyMDone
;
KeyM132: ; set sState to load
ldi rmp,0x01
rcall KeyChSet
rcall KeyClrUnl ; clear the channel's unload bit
rcall KeyClrCap
ldi rmp,128 ; set pwm to 1100 mV
rcall KeySetPwm
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM132D)
ldi ZL,LOW(2*KeyTxtM132D)
rjmp KeyMDone
;
KeyM133: ; set sState to maintain
ldi rmp,0x01
rcall KeyChSet
rcall KeyClrUnl ; clear the channel's unload bit
ldi rmp,128 ; set the pwm to 1100 mV
rcall KeySetPwm
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM133D)
ldi ZL,LOW(2*KeyTxtM133D)
rjmp KeyMDone
;
KeyM134: ; clear sState
clr rmp
rcall KeyChSet
rcall KeyClrUnl
clr rmp
rcall KeySetPwm
rcall KeyClrCap
ldi XH,HIGH(KeyM13a)
ldi XL,LOW(KeyM13a)
ldi ZH,HIGH(2*KeyTxtM134D)
ldi ZL,LOW(2*KeyTxtM134D)
rjmp KeyMDone
;
KeyTxtM131D:
.DB "Ch unload",0
KeyTxtM132D:
.DB "Ch load",0
KeyTxtM133D:
.DB "Ch maint ",0
KeyTxtM134D:
.DB "Ch clear ",0
;
; =================== Menue tables ===================
;
; Menue 1
;
KeyTxtM1:
.DB "Select...#",0,18
.DW KeyM11
.DB "Set...# ",0,15
.DW KeyM12
.DB "Command...# ",0,19
.DW KeyM13
.DW 0xFFFF
;
KeyTxtM11:
.DB "Akku...#",0,16
.DW KeyM111
.DB "Channel...# ",0,19
.DW KeyM112
.DB "Directload# ",0,19
.DW KeyM113
.DW 0xFFFF
;
KeyTxtM12:
.DB "Unload...#",0,18
.DW KeyM121
.DB "Load...#",0,16
.DW KeyM122
.DB "Capacity..# ",0,19
.DW KeyM123
.DB "Maintain..# ",0,19
.DW KeyM124
.DW 0xFFFF
;
KeyTxtM13:
.DB "Unload...#",0,18
.DW KeyM131
.DB "Load...#",0,16
.DW KeyM132
.DB "Maintain..# ",0,19
.DW KeyM133
.DB "Clear...# ",0,17
.DW KeyM134
.DW 0xFFFF
;

http://www.avr-asm-tutorial.net/akkuload/en/akkukey.asm (2 of 2)1/20/2009 7:51:20 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkulcd.asm

; **************************************************************
; * Include file LCD routines for Akkuload, Version 0.1 02/05 *
; * (C)2005 by Gerhard Schmidt, info@avr-asm-tutorial.net *
; **************************************************************
;
; --------------------------------------------------------------
; Provides Uses Function performed
; --------------------------------------------------------------
; LcdInit rmp,R0,Z Inits the display from scratch to:
; 8-bit-interface, 4 lines, no shift,
; active cursor and blinking
; LcdR0 rmp outputs the character in R0 on the
; current position of the LCD, R0 is
; preserved
; LcdChar rmp,R0 outputs the character in rmp on the
; current position of the LCD, rmp is
; changed and preserved in R0
; LcdDisplZ rmp,R0,Z output text in flash at adress Z to Lcd,
; stop at null char
; LcdLine rmp sets input cursor of the LCD to the
; selected line in rmp, expects 0..3 in
; rmp for line 1..4
; LcdLineCl rmp,R0,Z clears the line that rmp points to by
; writing blanks to it
; LcdPos rmp,Z sets the LCD to the position in Z,
; ZH is the line, ZL is the position in
; that line
; LcdMClr rmp clears the menue part and sets position
; to the beginning of this area
; LcdMStrt rmp,R0,Z Sets the LCD cursor position to the
; menue start
; LcdCursor rmp,Z Sets the LCD cursor to its correct
; current position, position<8: display
; menue
; LcdHex2 rmp writes the content of rmp in Hex to the
; LCD's current position
; LcdDec5 rmp,R0,Z writes the binary number in R3:R2 as
; LcdDec4 decimal to the LCD's current position,
; LcdDec3 5, 4, 3 or 2 digits are displayed
; LcdDec2
; --------------------------------------------------------------
;
; Constants
;
.EQU pLcdCO = PORTD
.EQU pLcdCD = DDRD
.EQU pLcdCI = PIND
.EQU pLcdDO = PORTB
.EQU pLcdDD = DDRB
.EQU pLcdDI = PINB
.EQU bLcdE = 2 ; E of the display
.EQU bLcdRw = 3 ; Read/Write control of the display
.EQU bLcdRs = 4 ; Register select of the display
;
; Delays for the LCD display initialisation
; Number of clocks including rcall: 3+7+4*Z-4+7 = 4*Z+13
; Delay in s: (4*Z+13)/8
; Calculating Z = (8*t[s]-13)/4
;
; Delay 15 ms
;
.EQU cLcdWt15000 = (8*15000-13)/4 ; = 29996
LcdWt15000:
ldi ZH,HIGH(cLcdWt15000) ; 1
ldi ZL,LOW(cLcdWt15000) ; 2
rjmp LcdWt ; 4
;
; Delay 4,1 ms
;
.EQU cLcdWt4100 = (8*4100-13)/4 ; = 8196
LcdWt4100:
ldi ZH,HIGH(cLcdWt4100) ; 1
ldi ZL,LOW(cLcdWt4100)
rjmp LcdWt
;
; Delay 4.5 ms
;
.EQU cLcdWt4500 = (4500*8-13)/4
LcdWt4500:
ldi ZH,HIGH(cLcdWt4500) ; 1
ldi ZL,LOW(cLcdWt4500) ; 2
rjmp LcdWt ; 4
;
; Delay 1.64 ms
;
.EQU cLcdWt1640 = (1640*8-13)/4 ; = 3276
LcdWt1640:
ldi ZH,HIGH(cLcdWt1640) ; 1
ldi ZL,LOW(cLcdWt1640) ; 2
rjmp LcdWt ; 4
;
; Delay 100 s
;
.EQU cLcdWt100 = (100*8-13)/4
LcdWt100:
ldi ZH,HIGH(cLcdWt100)
ldi ZL,LOW(cLcdWt100)
rjmp LcdWt
;
; Delay 40 s
;
.EQU cLcdWt40 = (40*8-13)/4 ; = 76
LcdWt40:
ldi ZH,HIGH(cLcdWt40) ; 1
ldi ZL,LOW(cLcdWt40) ; 2
nop ; 3
nop ; 4
;
; Waits for Z delay
; Number of clocks including ret = 4*(Z-1)+7
; Delay in s @8Mcs/s: (4*(Z-1)+7)/8
;
LcdWt:
sbiw ZL,1 ; 2
brne LcdWt ; 2/1
ret ; 4
;
; Delay for an active E pulse is 1 s
;
LcdDel1:
nop
ret
;
; Activate E for 1 s
;
LcdE:
sbi pLcdCO,bLcdE ; set E
rcall LcdDel1 ; 1 s Delay
cbi pLcdCO,bLcdE ; clear E
ret
;
; Check if Lcd is busy after sending a character
;
LcdChck:
cbi pLcdCO,bLcdRw ; Write data
sbi pLcdCO,bLcdRs ; set RS
clr rmp ; all data bits to input
out pLcdDD,rmp
ser rmp ; switch the pullup-resistors on
out pLcdDO,rmp
cbi pLcdCO,bLcdRs ; clr Rs
sbi pLcdCO,bLcdRw ; set Rw
sbi pLcdCO,bLcdE ; activate E
in rmp,pLcdDI ; read display
tst rmp ; jump if adress and busy flag are not zero
sbr rFlg,1<<bLcdOk ; set lcd ok flag
cbi pLcdCO,bLcdE ; clear E
cbi pLcdCO,bLcdRw ; clear Rw
ret
;
; Function set on init
;
LcdInitFunct:
cbi pLcdCO,bLcdRs ; clear RS
cbi pLcdCO,bLcdRw ; clear RW
ldi rmp,0x38 ; Set 8 bit interface, 2 Lines
out pLcdDO,rmp ; to output
rcall LcdE
rcall LcdWt4100 ; wait 4100 s
rcall LcdE
rcall LcdWt100 ; wait 100 s
rcall LcdE
rcall LcdWt100 ; wait 100 s
ldi rmp,0x08 ; Display off
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; wait 40 s
ldi rmp,0x01 ; Clear Display
out pLcdDO,rmp
rcall LcdE
; rcall LcdWt1640 ; wait 1.64 ms
rcall LcdWt4500 ; wait 4.5 ms
ldi rmp,0x06 ; Entry mode, increase, do not shift display
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40
ldi rmp,0x10 ; Display cursor shift
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; wait 40 s
ldi rmp,0x02 ; Display/Cursor Home
out pLcdDO,rmp
rcall LcdE
rcall LcdWt1640 ; wait for 1,64 ms
ldi rmp,0x0F ; Display active, Cursor on, blink cursor
out pLcdDO,rmp
rcall LcdE
rcall LcdWt40 ; wait 40 s
rjmp LcdChck ; check the LCD
;
; Wait until the LCD isn't busy any more
;
LcdBusy:
clr rmp ; Set Data port to input
out pLcdDD,rmp
cbi pLcdCO,bLcdRs ; Clear RS
sbi pLcdCO,bLcdRw ; Set display to read
sbi pLcdCO,bLcdE ; Enable Lcd
LcdBusy1:
nop ; wait a bit
nop ; anoth wait a bit
sbic pLcdDI,7 ; skip if bit 7 is zero
rjmp LcdBusy1
cbi pLcdCO,bLcdE ; Clear E
ret
;
; Send control instruction in rmp to LCD
;
LcdCtrl:
push rmp ; save rmp
rcall LcdBusy
ldi rmp,0xFF ; Set data port to output
out pLcdDD,rmp
pop rmp
out pLcdDO,rmp ; data to port
cbi pLcdCO,bLcdRs ; clear RS
cbi pLcdCO,bLcdRw ; clear R/W
rcall LcdE ; activate E for 1 s
clr rmp ; Data port off
out pLcdDD,rmp
ret
;
; Write character in rmp to LCD
;
LcdChar:
mov R0,rmp ; copy character to R0
;
; Write character in R0 to LCD
;
LcdR0:
rcall LcdBusy
ldi rmp,0xFF ; Data output direction
out pLcdDD,rmp
out pLcdDO,R0 ; data char to port
sbi pLcdCO,bLcdRs ; Set RS
cbi pLcdCO,bLcdRw ; clear R/W
rcall LcdE ; activate E for 1 s
clr rmp ; deactivate data port
out pLcdDD,rmp
ret
;
; Display text Z to display
;
LcdDisplZ:
lpm ; read a char
adiw ZL,1
tst R0 ; zero char?
breq LcdDisplZ1
rcall LcdR0 ; display char
rjmp LcdDisplZ
LcdDisplZ1:
ret
;
; Init the LCD
;
LcdInit:
ser rmp ; Set Data Port to all output
out pLcdDD,rmp
cbi pLcdCO,bLcdE ; Bit E to zero
sbi pLcdCD,bLcdE ; Direction bit E is output
cbi pLCDCO,bLcdRw ; Bit R/W to zero
sbi pLcdCD,bLcdRw ; Direction bit R/W is output
cbi pLcdCO,bLcdRs ; Bit RS to zero
sbi pLcdCD,bLcdRs ; Direction bit RS is output
rcall LcdWt15000 ; Wait for 15 ms
rcall LcdInitFunct ; Set 8-bit interface+number of lines
rcall LcdChck ; check the lcd
sbrs rFlg,bLcdOk ; jump if Lcd is ok
ret
clr rmp ; set Lcd Line 1
rcall LcdLine
ldi ZH,HIGH(2*LcdTxtInit1)
ldi ZL,LOW(2*LcdTxtInit1)
rcall LcdDisplZ
ldi rmp,1 ; set LCD Line 2
rcall LcdLine
rcall LcdDisplZ
ldi rmp,2 ; set Lcd Line 3
rcall LcdLine
rcall LcdDisplZ
ldi rmp,3 ; set Lcd Line 4
rcall LcdLine
rjmp LcdDisplZ
;
; LcdLine sets input cursor to the selected line in rmp
;
LcdLine:
cpi rmp,1 ; rmp = 0 or 1
brcs LcdLine1 ; rmp=0, set line 1
breq LcdLine2 ; rmp=1, set line 2
cpi rmp,2
breq LcdLine3 ; rmp=2, set line 3
ldi rmp,0x54 ; rmp>2, set line 4
rjmp LcdLine4
LcdLine1:
clr rmp ; Line 1 starts at 0
rjmp LcdLine4
LcdLine2:
ldi rmp,0x40 ; Line 2 starts at 0x40
rjmp LcdLine4
LcdLine3:
ldi rmp,20 ; Line 3 starts at 20
LcdLine4:
sbr rmp,0x80
rjmp LcdCtrl
;
; Lcd clear line
;
LcdLineCl:
mov ZH,rmp ; save line number
rcall LcdLine ; set line
ldi rmp,' ' ; blank
mov R0,rmp ; move to R0
ldi ZL,20 ; ZL is counter
LcdLineCl1:
rcall LcdR0 ; write blank
dec ZL ; next
brne LcdLineCl1 ; again
mov rmp,ZH ; restore rmp
rjmp LcdLine
;
; LcdPos sets the LCD to the position in Z
;
LcdPos:
cpi ZH,1 ; line = 0 or 1
brcs LcdPos1 ; ZH=0, set line 1
breq LcdPos2 ; ZH=1, set line 2
cpi ZH,2
breq LcdPos3 ; ZH=2, set line 3
ldi rmp,0x54 ; ZH>2, set line 4
rjmp LcdPos4
LcdPos1:
clr rmp ; Line 1 starts at 0
rjmp LcdPos4
LcdPos2:
ldi rmp,0x40 ; Line 2 starts at 0x40
rjmp LcdPos4
LcdPos3:
ldi rmp,20 ; Line 3 starts at 20
LcdPos4:
add rmp,ZL ; add position in line
sbr rmp,0x80
rjmp LcdCtrl
;
; Sets the LCD cursor to its correct position
;
LcdCursor:
sbrs rFlg,bLcdOk ; is the Lcd ok?
ret
lds rmp,sLcdCs ; read cursor position
cpi rmp,8 ; minimum position
brcc LcdCursor1
rcall KeyMenueFirst ; display menue on line
LcdCursor1:
ldi ZH,3 ; Line 3
lds ZL,sLcdCs ; read cursor position again
rjmp LcdPos
;
; LCDHEX2 writes the content of rmp in Hex
;
LcdHex2:
push rmp
swap rmp
rcall LcdHexN
pop rmp
LcdHexN:
andi rmp,0x0F
cpi rmp,0x0A
brcs LcdHexN1
subi rmp,-7
LcdHexN1:
subi rmp,-'0'
rcall LcdChar
ret
;
; LcdDecDigit subtracts the decimal and writes the digit
;
LcdDecDigit:
clr rmp ; counts during subtraction
LcdDecDigit1:
cp R2,ZL ; compare number LSB
cpc R3,ZH ; dto., MSB
brcs LcdDecDigit2 ; subtraction ended
sub R2,ZL ; subtract LSB
sbc R3,ZH ; dto., MSB
inc rmp ; count number of subtractions
rjmp LcdDecDigit1 ; go on
LcdDecDigit2:
tst rmp ; zero times?
brne LcdDecDigit3 ; no
tst R0 ; check leading zero still active
brne LcdDecDigit3
ldi rmp,' ' ; leading blank
rcall LcdChar ; display blank
clr R0
ret
LcdDecDigit3:
subi rmp,-'0' ; add ASCII-null
rcall LcdChar ; display digit on Lcd
clr R0 ; no leading zeros any more
inc R0
ret
;
; LcdDec writes the number in R3:R2 in decimal to the display
; 5, 4, 3 or 2 digits are displayed
;
LcdDec5:
clr R0 ; leading zero flag
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall LcdDecDigit
LcdDec4:
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall LcdDecDigit
LcdDec3:
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall LcdDecDigit
LcdDec2:
clr ZH
ldi ZL,10
rcall LcdDecDigit
ldi rmp,'0'
add rmp,R2
rjmp LcdChar
;
; End of routines
;
; Lcd texts
;
; Init text on display
;
LcdTxtInit1:
.DB "Akkuloader V1.0",0
LcdTxtInit2:
.DB "(C)2005 by DG4FAC",0
LcdTxtInit3:
.DB "Four channel akku",0
LcdTxtInit4:
.DB "loader processor ",0
;
; End of lcd include file
;

http://www.avr-asm-tutorial.net/akkuload/en/akkulcd.asm1/20/2009 7:51:22 PM
http://www.avr-asm-tutorial.net/akkuload/en/akkuuart.asm

; **************************************************************
; * Include file with the UART command line processing *
; * (C)2005 by Gerh.Schmidt info@avr-asm-tutorial.net *
; **************************************************************
;
; Provides the following routines for outside use
;
; Routine Uses Provides
; --------------------------------------------------------------
; UartInit rmp Inits the UART receiver and trans-
; mitter
; UartSendChar Sends the char in rmp over the Uart
; UartSendOpenText rmp,R0,Z Sends the opening message
; UartDec5 X,rmp Displays the binary in R3:R2 in de-
; UartDec4 cimal over Uart, R0>0: display
; UartDec3 leading zeroes
; UartDec2
; UartSendN5 X,rmp Displays the binary in R3:R2 in de-
; UartSendN4 cimal over Uart with a fixed length,
; UartSendN3 R0>0: display leading zeroes
; UartSendN2
; UartHexB rmp Send the hex byte in rmp to the Uart
; UartHex16 rmp,R0,Z Sends 16 bytes with adress in Z over
; the Uart
; --------------------------------------------------------------
;
;
; Init UART
;
.EQU cUbrr = fClock/16/baud - 1 ; Baudrate generator constant
;
UartInit:
ldi rmp,HIGH(cUbrr) ; Init UART Baudrate generator
out UBRRH,rmp
ldi rmp,LOW(cUbrr)
out UBRRL,rmp
ldi rmp,(1<<RXEN)|(1<<TXEN) ; Enable RX and TX
out UCSRB,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; 8N1
out UCSRC,rmp
in rmp,UDR; Clear Rx-Buffer
in rmp,UDR
in rmp,UDR
ldi rmp,LOW(sUartRxBs) ; Set buffer pointer to start
sts sUartRxBp,rmp
clr rmp ; Init current channel
sts sUartCurCh,rmp
clr rFlg ; Clear Flag
ldi rmp,(1<<RXEN)|(1<<TXEN)|(1<<RXCIE) ; Enable RX-Int
out UCSRB,rmp
ret
;
;
; **************** Subroutines ********************************
;
; Send the char in rmp to the SIO
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty TX
rjmp UartSendChar
out UDR,rmp ; send the char in rmp
ret
;
; Send text in flash (Z points to) to Uart
;
UartSendZ:
lpm ; read next character from flash
adiw ZL,1
tst R0 ; Null-character?
brne UartSendR0 ; No, send over Uart
ret
UartSendR0:
mov rmp,R0 ; copy character
rcall UartSendChar ; send character
rjmp UartSendZ ; next character
;
; Send opening message
;
UartSendOpenText:
ldi ZH,HIGH(2*UartTxtOpening) ; Point Z to text
ldi ZL,LOW(2*UartTxtOpening)
rcall UartSendZ ; send the text Z is pointing to
lds R2,sEANm ; read number of accu id's
clr R3
clr R0
rcall UartSendN2
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
;
; Subtract repeat and send if R0>0
;
UartSubt:
clr rmp ; result is here
UartSubt1:
sub R2,XL ; subtract LSB
sbc R3,XH ; subtract MSB
brcs UartSubt2
inc rmp
rjmp UartSubt1
UartSubt2:
add R2,XL ; add subractor again
adc R3,XH
add R0,rmp
breq UartSubt3
subi rmp,-'0' ; add ASCII null
rcall UartSendChar
UartSubt3:
ret
;
; Send a number over UART, number is in R3:R2
;
UartSendNmbr:
clr R0
UartDec5:
ldi XH,HIGH(10000)
ldi XL,LOW(10000)
rcall UartSubt
UartDec4:
ldi XH,HIGH(1000)
ldi XL,LOW(1000)
rcall UartSubt
UartDec3:
clr XH
ldi XL,100
rcall UartSubt
UartDec2:
clr XH
ldi XL,10
rcall UartSubt
ldi rmp,'0'
add rmp,R2
rjmp UartSendChar
;
; Send a fixed decimal
;
UartSubN:
clr rmp ; result is here
UartSubN1:
sub R2,XL ; subtract LSB
sbc R3,XH ; subtract MSB
brcs UartSubN2
inc rmp
rjmp UartSubN1
UartSubN2:
add R2,XL ; add subractor again
adc R3,XH
add R0,rmp
subi rmp,-'0' ; add ASCII null
tst R0
brne UartSubN3
ldi rmp,' '
UartSubN3:
rjmp UartSendChar
;
; Send a number in R3:R2 with a fixed length
;
UartSendN5:
ldi XH,HIGH(10000)
ldi XL,LOW(10000)
rcall UartSubN
UartSendN4:
ldi XH,HIGH(1000)
ldi XL,LOW(1000)
rcall UartSubN
UartSendN3:
clr XH
ldi XL,100
rcall UartSubN
UartSendN2:
clr XH
ldi XL,10
rcall UartSubN
ldi rmp,'0'
add rmp,R2
rjmp UartSendChar
;
; Sends a byte in rmp in hex to Uart
;
UartHexB:
push rmp ; save byte
swap rmp
rcall UartHexN
pop rmp
UartHexN:
andi rmp,0x0F
cpi rmp,10
brcs UartHexN1
subi rmp,-7
UartHexN1:
subi rmp,-'0'
rjmp UartSendChar
;
; UartHex16 sends 16 Bytes in Hex starting at Z
;
UartHex16:
mov rmp,ZH
rcall UartHexB
mov rmp,ZL
rcall UartHexB
ldi rmp,16
mov R0,rmp
UartHex16a:
ldi rmp,' ';
rcall UartSendChar
ld rmp,Z+
rcall UartHexB
dec R0
brne UartHex16a
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartSendCursor
;
; UART return, restore RX buffer, send cursor
;
UartRxRet:
ldi rmp,LOW(sUartRxBs) ; Set buffer pointer to start
sts sUartRxBp,rmp
cbr rFlg,(1<<bUartRxLine) ; clear rx line flag
UartSendCursor:
ldi rmp,'A' ; send current akku number
rcall UartSendChar
lds rmp,sUartCurCh
subi rmp,-'1' ; add ASCII 1
rcall UartSendChar
ldi rmp,'>' ; send cursor
rjmp UartSendChar
;
; Skips leading blanks, = , " , and komma
; returns with Carry set and error message in Z, if end of
; input line is reached
;
UartSkipLeading:
lds R1,sUartRxBp ; read end of input line
UartSkipLeading1:
cp XL,R1
brcs UartSkipLeading2 ; not at the end
ldi ZH,HIGH(2*UartTxtUnexEol) ; Error message
ldi ZL,LOW(2*UartTxtUnexEol)
sec ; set carry
ret
UartSkipLeading2:
ld rmp,X+ ; read char from line
cpi rmp,'='
breq UartSkipLeading1
cpi rmp,','
breq UartSkipLeading1
cpi rmp,' '
breq UartSkipLeading1
cpi rmp,'"'
breq UartSkipLeading1
sbiw XL,1
clc
ret
;
; Get next digit, carry if end of line, zero if end of number
;
UartGetDigit:
lds R1,sUartRxBp ; read end of input line
cp XL,R1
brcs UartGetDigit1 ; not at the end
ldi ZH,HIGH(2*UartTxtUnexEol) ; Error message
ldi ZL,LOW(2*UartTxtUnexEol)
sec ; set carry
ret
UartGetDigit1:
ld rmp,X+ ; read digit
cpi rmp,' ' ; end of number?
breq UartGetDigitEnd
cpi rmp,cCr
breq UartGetDigitEnd
cpi rmp,','
breq UartGetDigitEnd
subi rmp,'0' ; make binary
brcs UartGetDigitIll
cpi rmp,10 ; too big?
brcc UartGetDigitIll
clc ; anything ok
clz
ret
UartGetDigitIll:
ldi ZH,HIGH(2*UartTxtNmbrErr) ; Illegal char in number
ldi ZL,LOW(2*UartTxtNmbrErr)
sec ; set carry for error
UartGetDigitEnd:
ret
;
; Get a decimal number from the received line
;
UartGetDec:
rcall UartSkipLeading
brcs UartGetDec3 ; return with carry set for error
clr R2 ; Result LSB
clr R3 ; Result MSB
UartGetDec1:
rcall UartGetDigit ; read the next digit
brcs UartGetDec3 ; return with carry set for error
breq UartGetDec4 ; end of number reached
mov R0,R2 ; Copy Result
mov R1,R3
add R2,R2 ; Result*2
adc R3,R3
brcs UartGetDec2 ; number overflow
add R2,R2 ; Result*4
adc R3,R3
brcs UartGetDec2 ; number overflow
add R2,R0 ; Result*5
adc R3,R1
brcs UartGetDec2 ; number overflow
add R2,R2 ; Result*10
adc R3,R3
brcs UartGetDec2 ; number overflow
add R2,rmp ; add digit
ldi rmp,0
adc R3,rmp
brcc UartGetDec1 ; no number overflow, next char
UartGetDec2:
ldi ZH,HIGH(2*UartTxtNmbrOvf) ; Number overflow
ldi ZL,LOW(2*UartTxtNmbrOvf)
sec
UartGetDec3: ; number error
ret
UartGetDec4: ; number is fine and complete
clc
ret
;
; ****************** RX line **********************
;
; A complete UART RX line has been received, answer
;
UartRxLine:
ldi rmp,LOW(UartRxRet) ; Put UartRxRet to stack
push rmp
ldi rmp,HIGH(UartRxRet)
push rmp
ldi ZH,HIGH(2*UartCmds) ; point Z to command list
ldi ZL,LOW(2*UartCmds)
UartRxLine1:
lpm ; Test end of command list
mov rmp,R0 ; FF signals end of command list
cpi rmp,0xFF
brne UartRxLine3
UartRxLine2: ; End of command list, unknown command
ldi ZH,HIGH(2*UartTxtUnkCmd) ; Send unknown command
ldi ZL,LOW(2*UartTxtUnkCmd)
rjmp UartSendZ
UartRxLine3: ; Start comparing
ldi XH,HIGH(sUartRxBs) ; point X to received line
ldi XL,LOW(sUartRxBs)
UartRxLine4:
lds rmp,sUartRxBp ; read buffer pointer
cp XL,rmp ; end of input buffer reached?
brcs UartRxLine7 ; no, go on
UartRxLine5: ; skip this command, go to next command
lpm ; read next command char
adiw ZL,1 ; point Z to next char
mov rmp,R0 ; End of command text char
cpi rmp,'#' ; end sign reached?
brne UartRxLine5 ; no
lpm ; Is the next char a blank?
mov rmp,R0
cpi rmp,' '
brne UartRxLine6
adiw ZL,1
UartRxLine6:
adiw ZL,7 ; jump over the rest of the command
rjmp UartRxLine1
UartRxLine7:
lpm ; Read char from flash
mov rmp,R0 ; copy char from flash
cpi rmp,'#' ; end of the command?
breq UartRxLine8
ld rmp,X+ ; read next char from buffer
sbr rmp,0x20 ; to small character
cp rmp,R0 ; equal char?
brne UartRxLine5 ; no, skip the command
adiw ZL,1 ; next char
rjmp UartRxLine4 ; to next char in buffer
UartRxLine8:
adiw ZL,1 ; blank behind #?
lpm
mov rmp,R0
cpi rmp,' '
brne UartRxLine9
adiw ZL,1
UartRxLine9:
lds rmp,sUartRxBp ; End of buffer reached?
cpc XL,rmp
brcc UartRxLine2
ld rmp,X+ ; read next char from buffer
cpi rmp,cCr ; End of command?
brne UartRxLine10 ; with Parameter
; Command without parameters
adiw ZL,5 ; Point Z to address
lpm ; read LSB
push R0
adiw ZL,1 ; read MSB
lpm
push R0
clc ; no parameter given
ret ; jump to command
UartRxLine10: ; Command line with parameter
cpi rmp,'=' ; Parameter?
brne UartRxLine5 ; No, search next command
lpm ; read number of parameters
tst R0
brne UartRxLine11 ; command has parameter
ldi ZH,HIGH(2*UartTxtParaErr) ; Error message
ldi ZL,LOW(2*UartTxtParaErr)
rjmp UartSendZ
UartRxLine11: ; Command line parameter
rcall UartGetDec ; get the decimal number
brcc UartRxLine17 ; number is fine
rjmp UartSendZ ; error message
UartRxLine17:
adiw ZL,1 ; Read LSB min parameter
lpm
adiw ZL,1
cp R2,R0 ; compare lsb
lpm ; Read MSB min parameter
cpc R3,R0 ; compare msb
brcs UartRxLine18
adiw ZL,1 ; Read LSB max parameter
lpm
adiw ZL,1
sec ; Set carry for Max+1
cpc R2,R0 ; compare lsb
lpm ; Read MSB max parameter
cpc R3,R0 ; compare msb
brcs UartRxLine19 ; number is fine
UartRxLine18: ; number out of range
ldi ZH,HIGH(2*UartTxtNmbrOor)
ldi ZL,LOW(2*UartTxtNmbrOor)
rjmp UartSendZ
UartRxLine19: ; Read adress and jump
adiw ZL,1 ; read LSB
lpm
push R0 ; LSB on stack
adiw ZL,1 ; read MSB
lpm
push R0 ; MSB on stack
sec ; set carry, parameter
ret ; jump to command adress
;
; ***************** Commands *********************************
;
; Uart command HELP
;
UartHelp:
ldi ZH,HIGH(2*UartTxtHelp) ; Help message
ldi ZL,LOW(2*UartTxtHelp)
rjmp UartSendZ
;
; Uart command RESTART
;
UartRestart:
pop rmp ; destroy return adress
pop rmp
jmp 0 ; start new
;
; Uart command Channel
;
UartChannel:
brcc UartChannel1
dec R2
sts sUartCurCh,R2
UartChannel1: ; Output channel number
ldi ZH,HIGH(2*UartTxtCurrCh)
ldi ZL,LOW(2*UartTxtCurrCh)
rcall UartSendZ
lds rmp,sUartCurCh ; read current channel
subi rmp,-'1' ; add ASCII-one
rcall UartSendChar
adiw ZL,1 ; complete output
rjmp UartSendZ
;
; Gets the akku Id adress of the current channel
;
UartGetAkkuId:
ldi ZH,HIGH(sAdcAI1) ; Z to akku id 1
ldi ZL,LOW(sAdcAI1)
lds rmp,sUartCurCh
add ZL,rmp
add ZL,rmp
ret
;
; Set the akku id of the current channel
;
UartAkkuId:
brcc UartAkkuId1
rcall UartGetAkkuId
st Z,R2
lds R0,sUartCurCh
rcall IdSetPar
UartAkkuId1:
ldi ZH,HIGH(2*UartTxtAkkuId)
ldi ZL,LOW(2*UartTxtAkkuId)
rcall UartSendZ
rcall UartGetAkkuId
ld R2,Z
clr R3
clr R0
rcall UartDec2
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartOutSettings
;
; Point rmp to current unload bit
;
UartUnloadBit:
lds R0,sUartCurCh
ldi rmp,0x10
UartUnloadBit1:
tst R0
breq UartUnloadBit2
lsl rmp
dec R0
rjmp UartUnloadBit1
UartUnloadBit2:
;
; Point X to Pwm-Channel pwm register
;
UartChannX:
clr XH ; Point to channel pwm value
ldi XL,cPwm1S
lds R0,sUartCurCh ; add current channel
add XL,R0
ret
;
; Get the Uart current parameter adress in X
;
UartGetChPar:
lds R1,sUartCurCh ; read channel
lsl R1
lsl R1
lsl R1
ldi XH,HIGH(sCh1UV) ; Base address
ldi XL,LOW(sCh1UV)
add XL,R1
brcc UartGetChPar1
inc XH
UartGetChPar1:
ret
;
; Get adress of channel activity text in Z
;
UartGetChAct:
ldi ZH,HIGH(2*UartTxtAct)
ldi ZL,LOW(2*UartTxtAct)
lds R1,sUartCurCh ; current channel
lds rmp,sState ; get channel states
UartGetChAct1:
tst R1
breq UartGetChAct2
lsr rmp
lsr rmp
dec R1
rjmp UartGetChAct1
UartGetChAct2:
andi rmp,0x03 ; isolate bits
breq UartGetChAct4
UartGetChAct3:
lpm
adiw ZL,1
tst R0
brne UartGetChAct3
dec rmp
rjmp UartGetChAct2
UartGetChAct4:
ret
;
; Set the unload threshhold voltage
;
UartSetU:
brcc UartSetU1
rcall UartGetChPar ; get address in X
st X+,R2 ; store parameter there
st X,R3
UartSetU1:
rjmp UartOutSettings
;
; Set the load current on that channel
;
UartSetI:
brcc UartSetI1
rcall UartGetChPar ; get address in X
adiw XL,2 ; load current is the second par
st X+,R2 ; store the received number there
st X,R3
UartSetI1:
rjmp UartOutSettings
;
; Set the total work to be loaded
;
UartSetW:
brcc UartSetW1 ; no parameter given
rcall UartGetChPar ; get address in X
adiw XL,4 ; work is the third par
st X+,R2 ; store the received number there
st X,R3
UartSetW1:
rjmp UartOutSettings
;
; Set the maintain current
;
UartSetM:
brcc UartSetM1
rcall UartGetChPar ; get address in X
adiw XL,6 ; the fourth variable
st X+,R2 ; store the parameter
st X,R3
UartSetM1:
rjmp UartOutSettings
;
; Set the state activity bits to the value in rmp
; input: rmp, bit 1 and 0 = activity flags
;
UartSetState:
lds R0,sUartCurCh ; load channel to R0
lds R2,sState ; load state bits to R2
mov R3,rmp ; save OR mask in R3
ldi rmp,0xFC ; prepare the mask for AND
mov R1,rmp
mov rmp,R3 ; restore original
UartSetState1:
tst R0 ; channel reached
breq UartSetState2
sec ; next channel
rol R1
sec
rol R1
lsl rmp ; shift activity bits two left
lsl rmp
lsr R2 ; shift state bits two right
lsr R2
dec R0
rjmp UartSetState1
UartSetState2:
lds R0,sState
and R0,R1 ; clear the two bits
or R0,rmp ; set the activity bits
sts sState,R0
mov rmp,R2 ; check the previous state
andi rmp,0x03 ; isolate state bits
cp rmp,R3 ; was the state changed?
breq UartSetState4 ; no, skip the correction
lds R0,sUartCurCh ; R0 is current channel
cpi rmp,0x02 ; previous state was load?
brne UartSetState3 ; inactive, unload or maintain
call EpStore ; save loaded capacity to EEPROM
sec
UartSetState3: ; clear accumulated capacity, if inactive or unload
call ClearCap ; clear capacity of channel in R0
UartSetState4:
rjmp UartOutSettings
;
; Set activity bits in channel status clear
;
UartClear:
ldi rmp,0x00
rjmp UartSetState
;
; Set the unload bit and clear channel pwm
;
UartUnload:
rcall UartUnloadBit
or rPwmOut,rmp
clr rmp
st X,rmp
ldi ZH,HIGH(2*UartTxtUnload)
ldi ZL,LOW(2*UartTxtUnload)
rcall UartSendZ
ldi rmp,0x01 ; Unload flags
rjmp UartSetState
;
; Set activity bits in channel status to maintaining
;
UartMaint:
ldi rmp,0x03
rjmp UartSetState
;
; Start loading on the actual channel
;
UartLoad:
ldi rmp,0x02
rjmp UartSetState
;
; Write the settings in a channel
;
UartOutSettings:
ldi rmp,4 ; R4 is counter
mov R4,rmp
ldi ZH,HIGH(2*UartTxtSettings)
ldi ZL,LOW(2*UartTxtSettings)
rcall UartSendZ
lds R1,sUartCurCh
ldi rmp,'1'
add rmp,R1
rcall UartSendChar
rcall UartSendZ
ldi XH,HIGH(sAdcAI1) ; write id
ldi XL,LOW(sAdcAI1)
lds rmp,sUartCurCh
add XL,rmp
add XL,rmp
ld R2,X
clr R3
rcall UartSendNmbr
rcall UartSendZ
push ZH
push ZL
rcall UartGetChAct
rcall UartSendZ
pop ZL
pop ZH
rcall UartSendZ
rcall UartGetChPar
UartOutSettings1:
ld R2,X+
ld R3,X+
push XH
push XL
rcall UartSendNmbr
rcall UartSendZ
pop XL
pop XH
dec R4
brne UartOutSettings1
ret
;
; Text for the settings
;
UartTxtSettings:
.DB "Ch ",0
.DB ": Id=",0
.DB ", status=",0
.DB ", U= ",0
.DB "mV, I= ",0
.DB "mA, C= ",0
.DB "mAh, Im= ",0
.DB "mA",$0D,$0A,0,0
;
; Activity status of the channel
;
UartTxtAct:
.DB "not connected",0
.DB "unloading",0
.DB "loading",0
.DB "maintaining",0
;
; Switch monitor on
;
UartMoniOn:
ldi rmp,1<<bUMoni
eor rFlgD,rmp
ldi ZH,HIGH(2*UartTxtMoniOff) ; Monitor is off
ldi ZL,LOW(2*UartTxtMoniOff)
and rmp,rFlgD
breq UartMoniOn1
ldi ZH,HIGH(2*UartTxtMoniOn) ; Monitor is on
ldi ZL,LOW(2*UartTxtMoniOn)
rcall UartSendZ
rjmp DispTimeUd ; display current time over Uart
UartMoniOn1: ; Monitoring switched off
rjmp UartSendZ
;
; Set a channel pwm value
;
UartPwm:
brcc UartPwm1
rcall UartUnloadBit
st X,R2 ; set current channel value
com rmp
and rPwmOut,rmp
UartPwm1:
ldi ZH,HIGH(2*UartTxtPwm) ; give text
ldi ZL,LOW(2*UartTxtPwm)
rcall UartSendZ
rcall UartUnloadBit
ld R2,X
clr R3
rcall UartSendNmbr
adiw ZL,1
rjmp UartSendZ
;
; Create a new akku id
;
UartNew:
brcs UartNew2 ; first parameter ok
ldi ZH,HIGH(2*UartTxtNewParamErr)
ldi ZL,LOW(2*UartTxtNewParamErr)
UartNew1: ; error message in Z
rjmp UartSendZ
UartNew2:
lds rmp,sEANm ; read number of available ids
cpi rmp,cEepMax+1 ; compare with max
brcc UartNew8 ; error too many
ldi ZH,HIGH(sEAId) ; point Z to buffer
ldi ZL,LOW(sEAId)
lds rmp,sEANm ; read max number
inc rmp ; next akku id
st Z,rmp ; store in buffer
adiw ZL,2 ; point to capacity
st Z+,R2 ; copy capacity in R3:R2 to buffer
st Z,R3
sbiw ZL,2 ; point to size
rcall UartGetDec ; get the size
brcs UartNew1 ; error
tst R3 ; check size
brne UartNew3
mov rmp,R2
cpi rmp,4
brcs UartNew4
UartNew3: ; illegal size
ldi ZH,HIGH(2*UartTxtNewSize)
ldi ZL,LOW(2*UartTxtNewSize)
rjmp UartSendZ
UartNew4:
subi rmp,0x5F ; -A0!
st Z,rmp ; store size
adiw ZL,3 ; point to number of loads
rcall UartGetDec ; get number of loads
brcs UartNew1 ; error
st Z+,R2 ; store in buffer
st Z+,R3
clr rmp
st Z+,rmp ; clear rest
st Z+,rmp
rcall UartSkipLeading
brcs UartNew1
ldi rmp,8 ; read 8 text bytes
mov R0,rmp
UartNew5:
ld rmp,X+ ; read char
cpi rmp,'"' ; end of text
breq UartNew6
cpi rmp,cCr
breq UartNew6
st Z+,rmp ; store in buffer
dec R0
brne UartNew5 ; next character
rjmp UartNew7 ; skip the rest
UartNew6:
tst R0
breq UartNew7
ldi rmp,' '
st Z+,rmp

http://www.avr-asm-tutorial.net/akkuload/en/akkuuart.asm (1 of 2)1/20/2009 7:51:26 PM


http://www.avr-asm-tutorial.net/akkuload/en/akkuuart.asm

dec R0
rjmp UartNew6
UartNew7:
call EpWrite
lds rmp,sEANm ; inc number of id's available
inc rmp
sts sEANm,rmp
ldi ZH,HIGH(2*UartTxtList) ; Header
ldi ZL,LOW(2*UartTxtList)
rcall UartSendZ
lds rmp,sEAId
rjmp UartList1
UartNew8: ; error too many id
ldi ZH,HIGH(2*UartTxtNewMany)
ldi ZL,LOW(2*UartTxtNewMany)
rjmp UartSendZ
;
; Lists the stored akku id's
;
UartList:
ldi ZH,HIGH(2*UartTxtList) ; Header
ldi ZL,LOW(2*UartTxtList)
rcall UartSendZ
clr R6 ; R6 is counter
UartList1:
inc R6
lds R0,sEANm ; load number of id's available
sec
cpc R6,R0 ; end of list?
brcc UartList3
mov rmp,R6
call EpRead ; read the id in rmp
ldi ZH,HIGH(sEAId) ; point Z to buffer
ldi ZL,LOW(sEAId)
ld R2,Z+ ; copy id number
clr R3
clr R0
rcall UartSendN2
ldi rmp,' '
rcall UartSendChar
ld rmp,Z+ ; Write size
rcall UartHexB
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Write capacity
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Write loads
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ld R2,Z+ ; Write rest capacity
ld R3,Z+
clr R0
rcall UartSendN5
ldi rmp,' '
rcall UartSendChar
ldi rmp,8
mov R1,rmp
UartList2:
ld rmp,Z+ ; read text
rcall UartSendChar
dec R1
brne UartList2
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rcall UartSendChar
rjmp UartList1 ; go on
UartList3:
ret
;
; ***************** tables ************************
;
; Commands, parameters and adress table for Uart commands
;
UartCmds:
.DB "help#",0 ; HELP command, no parameters
.DW 0,0,UartHelp
.DB "a# ",1 ; Akku channel select
.DW 1,4,UartChannel
.DB "n# ",1 ; Akku Id
.DW 0,32,UartAkkuId
.DB "u# ",1 ; Set unload off voltage
.DW 700,1200,UartSetU
.DB "i# ",1 ; Set load current in mA
.DW 5,350,UartSetI
.DB "c# ",1 ; Set capacity in mAh
.DW 10,2500,UartSetW
.DB "m# ",1 ; Set maintain current
.DW 5,100,UartSetM
.DB "clear# ",0 ; clear the channel
.DW 0,0,UartClear
.DB "unload#",0 ; Switch unload on
.DW 0,0,UartUnload
.DB "load#",0 ; Start loading
.DW 0,0,UartLoad
.DB "maintain#",0 ; Maintain
.DW 0,0,UartMaint
.DB "monitor# ",0 ; monitor on
.DW 0,0,UartMoniOn
.DB "pwm# ",1 ; PWM value for channel
.DW 0,255,UartPwm
.DB "new# ",1 ; create a new accu id
.DW 100,9000,UartNew
.DB "list#",0 ; List the stored akkus
.DW 0,0,UartList
.DB "restart# ",0 ; RESTART command, no parameters
.DW 0,0,UartRestart
.DW $FFFF ; End of command list
;
; Uart texts
;
UartTxtHelp:
.DB "Akkuload command list:",$0D,$0A
.DB "<help>, no param: this list.",$0D,$0A
.DB "<a> or <a=x>, param x (1..4): read/set akku channel number. ",$0D,$0A
.DB "<n> or <n=x>, param x (1..32): read/select akku id. ",$0D,$0A
.DB "<u> or <u=x>, param x (700..1200): read/set akku unload voltage.",$0D,$0A
.DB "<i> or <i=x>, param x (5..175): read/set load current in mA.",$0D,$0A
.DB "<c> or <c=x>, param x (10..9999): read/set capacity in mAh. ",$0D,$0A
.DB "<m> or <m=x>, param x (5..100): read/set maintain current in mA ",$0D,$0A
.DB "<clear>, no param: set the channel off. ",$0D,$0A
.DB "<unload>, no param: switches unload output on.",$0D,$0A
.DB "<load>, no param: start loading.",$0D,$0A
.DB "<maintain>, no param: switches to maintaining current.",$0D,$0A
.DB "<monitor>, no param: switches monitoring on.",$0D,$0A
.DB "<pwm> or <pwm=x>, param x (0..255): set pwm value.",$0D,$0A
.DB "<new=capacity, size, loads, text> creates new accu id,",$0D,$0A
.DB " capacity 100..9000, size 0..3, loads 0..65535, text free.",$0D,$0A
.DB "<list>, no param: list all stored accu id's.",$0D,$0A
.DB "<restart>, no param: restart the controller. ",$0D,$0A,$00
;
UartTxtOpening:
.DB $0D,$0A,$0D,$0A,"Akkuloader (C)2005 by info@avr-asm-tutorial.net ",$0D,$0A
.DB "----------------------------------------------- ",$0D,$0A
.DB "Stored accu id's : ",$00
.DB "Type 'help' <RETURN> for menue. ",$0D,$0A
;
UartTxtUnkCmd:
.DB "Unknown command! ",$0D,$0A,$00
;
UartTxtParaErr:
.DB "Command has no parameters! ",$0D,$0A,$00
;
UartTxtUnexEol:
.DB "Unexpected end of line!",$0D,$0A,$00
;
UartTxtNmbrErr:
.DB "Illegal character in number! ",$0D,$0A,$00
;
UartTxtNmbrOvf:
.DB "Number overflow! ",$0D,$0A,$00
;
UartTxtNmbrOor:
.DB "Number out of range! ",$0D,$0A,$00
;
UartTxtCurrCh:
.DB "Current akku channel is : ",$00,$20
.DB " ",$0D,$0A,$00
;
UartTxtPwm:
.DB "Current pwm value is : ",$00
.DB " ",$0D,$0A,$00
;
UartTxtUnload:
.DB "Unload bit has been set. ",$0D,$0A,$00
;
UartTxtMoniOff:
.DB "Monitoring is off. ",$0D,$0A,$00
;
UartTxtMoniOn:
.DB "Monitoring is on.",$0D,$0A,$00
;
UartTxtList:
.DB "Id Sz Capac Loads _Rest Text____",$0D,$0A,$00,$00
;
UartTxtAkkuId:
.DB "Current id is ",$00,$00
;
UartTxtNewParamErr:
.DB "Missing all parameters!",$0D,$0A,$00
;
UartTxtNewSize:
.DB "Illegal size!",$0D,$0A,$00
;
UartTxtNewMany:
.DB "Too many id's!",$0D,$0A,$00,$00
;

http://www.avr-asm-tutorial.net/akkuload/en/akkuuart.asm (2 of 2)1/20/2009 7:51:26 PM


Assembler Quellen für das AVR-Tutorial

Path: Home => AVR-Überlick => Quelldateien

Links zu allen Quelldateien dieses Tutorials


● 8515std.asm
● adc8.asm
● dcf77uhr.asm
● div8d.asm
● eieruhr.asm
● fp_conv10_de.asm
● fp_conv8_de.asm
● lcd_inc.asm
● lcd_test.asm
● mult8.asm
● pcm2pwg4.asm
● pwgsio2.asm
● Sägezahn1
● Sägezahn2
● Schrittmotor
● Sinus
● Sinustabelle
● Musik
● siohex.asm
● test1.asm
● test2.asm
● test3.asm
● test4.asm
● testeep.asm
● testjmp.asm
● testkbd.asm
● testlcd.asm
● testlpm.asm
● testmac1.asm
● testmac2.asm
● testmac3.asm
● testram.asm
● testsio.asm

©2002 - 2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_de/quellen/index.html1/20/2009 7:51:29 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/8515std.asm

; ***************************************************************
;* *

;* *

;* *

;* *

;* *

; * (C)2002 by Letzte Änderung: *


; ***************************************************************
;
; Hardware Anforderungen:
;
; Software Funktionen:
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Konstanten
;
.EQU xyz = 12345
;
; Benutzte Register
;
.DEF mpr = R16
;
; Code beginnt hier
;
.CSEG
.ORG $0000
;
; Reset- und Interrupt-Vektoren
;
rjmp Start ; Reset-vector
rjmp IInt0 ; External Interrupt Request 0
rjmp IInt1 ; External Interrupt Request 1
rjmp TCpt1 ; Timer/Counter1 Capture event
rjmp TCmpA ; Timer/Counter1 Compare match A
rjmp TCmpB ; Timer/Counter1 Compare Match B
rjmp TOvf1 ; Timer/Counter1 Overflow
rjmp TOvf0 ; Timer/Counter0 Overflow
rjmp SIStc ; SPI Serial Transfer Complete
rjmp URxAv ; Uart Rx char available
rjmp UTxDe ; Uart Tx data register empty
rjmp UTxCp ; Uart Tx complete
rjmp AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0

IInt0:

reti

; External Interrupt 1

IInt1:

reti

; Timer/Counter 1, Capture event


;
TCpt1:
reti
;
; Timer/Counter 1, Compare match interrupt A
;
TCmpA:
reti
;
; Timer/Counter 1, Compare match interrupt B
;
TCmpB:
reti
;
; Timer/Counter 1, Overflow interrupt
;
TOvf1:
reti
;
; Timer/Counter 0, Overflow interrupt
;
TOvf0:
reti
;
; SPI Serial Transfer Complete interrupt
SIStc:
reti
;
; Uart Rx Complete Interrupt

URxAv:

reti

; Uart Data register empty interrupt

UTxDe:

reti

; Uart Tx complete interrupt

UTxCp:

reti

; Analog comparator interrupt

AnaCp:

reti

; **************** Ende der Interrupt Service Routinen *********

; Verschiedene Unterprogramme

; **************** Ende der Unterprogramme *********************

; ******************** Hauptprogram ****************************

; Hauptprogramm beginnt hier

Start:

rjmp start

http://www.avr-asm-tutorial.net/avr_de/quellen/8515std.asm1/20/2009 7:51:30 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/lcd_test.asm

; *****************************************************
; * Demonstrates the use of the Include routines *
; * LCD_INC.ASM for use with the LCD on board of the *
; * ATMEL STK200 (C) 1999 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
.def mpr=R16 ; My multipurpose register, required
; Reset-/Interrupt-Vectors
rjmp main
; Includes the LCD-routines, file must be in the same path
.INCLUDE "LCD_INC.ASM"
; Main program
main:
ldi mpr,LOW(RAMEND) ; Set up stack
out SPL,mpr
ldi mpr,HIGH(RAMEND)
out SPH,mpr
ldi mpr,0xC0 ; Switch on external SRAM and WAIT
out MCUCR,mpr
rcall lcd_cl ; Clears display
rcall lcd_st ; Standard display mode
ldi mpr,0x05; Cursor position to line 1, col 5
rcall lcd_sc
ldi mpr,'H' ; Output Hello World
rcall lcd_ch
ldi mpr,'e'
rcall lcd_ch
ldi mpr,'l'
rcall lcd_ch
rcall lcd_ch
ldi mpr,'o'
rcall lcd_ch
ldi mpr,0x45 ; Cursor position to line 2, col 5
rcall lcd_sc
ldi mpr,'W'
rcall lcd_ch
ldi mpr,'o'
rcall lcd_ch
ldi mpr,'r'
rcall lcd_ch
ldi mpr,'d'
rcall lcd_ch
ldi mpr,'!'
rcall lcd_ch
rcall lcd_on
loop:
rjmp loop ; Uff! Next week we learn how to create and read a table

http://www.avr-asm-tutorial.net/avr_de/quellen/lcd_test.asm1/20/2009 7:51:32 PM
http://www.avr-asm-tutorial.net/avr_de/quellen/testkbd.asm

; Test des Keyboards


;
; Liest das Keyboard am Port B und zeigt die gedrückte Taste auf den LEDs
; in hexadezimaler Form aus.
;
; Keyboard ist an Port B angeschlossen:
; Bit 6: *=Bit0 7=Bit1 4=Bit2 1=Bit3
; Bit 5: 0=Bit0 8=Bit1 5=Bit2 2=Bit3
; Bit 4: #=Bit0 9=Bit1 6=Bit2 3=Bit3
;
; 8515-Definitionen
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Register
.def mpko=R15 ; Alter Tastenstand
.def mpr=R16 ; Multifunktionsregister
.def mpk=R25 ; Multifunktionsregister für Keyboard-Interrupt
;
; RAM-Adressen
.equ taste=$0060 ; Erste Ramadresse, Hier kommt die Taste hin
;
; Reset-/Interruptvektoren
rjmp main
reti ; Ext Int 0
reti ; Ext Int 1
reti ; TC1 Capture
rjmp test ; TC1 Compare A
reti ; Compare B
reti ; TC1 Overflow
reti ; TC0 Overflow
reti ; Serial Transfer Complete
reti ; Serial Rx Complete
reti ; Data Register Empty
reti ; Serial Tx Complete
reti ; Analog Comparator
; Hauptprogramm
main:
ldi mpr,HIGH(RAMEND) ; Stack Pointer Init wegen Interrupts
out SPH,mpr
ldi mpr,LOW(RAMEND)
out SPL,mpr
; General control register
clr mpr ; kein SRAM, kein Wait, kein Sleep-Mode,
out MCUCR,mpr ; Ext.Int egal
; Port B ist Output und Tastatur-Input
ldi mpr,0x70 ; alles auf Output
out DDRB,mpr
ldi mpr,0x00 ; alle Lampen an
out PORTB,mpr
sts Taste,mpr
;
; Timer/Counter 0 initiieren
ldi mpr,$00 ; Prescaler = 256
out TCCR0,mpr

; Timer 1 initiieren
ldi mpr,0b00000000 ; Disable Timer Output und PWM-Mode
out TCCR1A,mpr ; in Timer Control Register 1A
ldi mpr,0b00001011 ; No input noise canceling, clear counter after
; match, Prescaler = 64 ==> 62500 Hz = 16 µs
out TCCR1B,mpr ; in Timer Control Register 1B
ldi mpr,HIGH(625) ; Compare-Wert in Compare-Register A
out OCR1AH,mpr ; High Byte zuerst
ldi mpr,LOW(625)
out OCR1AL,mpr ; Low Byte zuletzt
ldi mpr,0xFF ; No Interrupt on Compare B
out OCR1BH,mpr ; High Byte zuerst
out OCR1BL,mpr ; Low Byte zuletzt
; Interrupts starten
clr mpr ; External interrupts disable
out GIMSK,mpr ; an General Interrupt mask register
ldi mpr,0b01000000 ; Timer 1: Overflow Int Off, Compare A Int on,
out TIMSK,mpr ; Compare B Int Off, Input Int Off, Timer 0: Int Off
sei ; Interrupts zulassen
; Unendlicher Loop, alles Interrupt-gesteuert
loop:
rjmp loop
; Interrupt Rountine bei TC1 Compare Match B
tc1ci:
in mpk,SREG ; Status-Register retten
push mpk
ldi mpk,0b11110000 ; Oberes Nibble Ausgabe, Unteres Eingabe
out DDRB,mpk ; an Port B
ldi mpk,0x0F ; Oberes Nibble gibt Null aus, unteres setzt Pullups
out PORTB,mpk
in mpk,PINB ; Lese Ergebnis von Tastatur
cp mpk,mpko ; Vergleiche mit altem Stand
breq tc1cir ; Keine Änderung, Rückkehr
mov mpko,mpk ; Kopiere neuen Stand in alten Stand
sts taste,mpk ; Neuer LED-Stand
tc1cir:
ldi mpk,0xFF ; Port B wieder auf Ausgabe
out DDRB,mpr
lds mpk,taste ; gedrückte Taste auf LEDs ausgeben
out PORTB,mpk
pop mpk ; Rückkehr vom Interrupt
out SREG,mpk ; Status-Register wieder herstellen
reti
tc0ci:
ldi mpr,0xFF
out PORTB,mpr
reti
tc2ci:
ldi mpr,0xAA
out PORTB,mpr
reti
test:
; LDI mpk,0x0F
; OUT DDRB,mpk
; LDI mpk,0xF0
; OUT PORTB,mpk
reti

http://www.avr-asm-tutorial.net/avr_de/quellen/testkbd.asm1/20/2009 7:51:33 PM
http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm

; ****************************************************
; * Frequenzzaehler, Drehzahlmesser und Voltmeter *
; * fuer ATmega8 bei 16 MHz Taktfrequenz (Quarzosz.) *
; * Version 0.2 (C)2005 by info@avr-asm-tutorial.net *
; ****************************************************
;
.INCLUDE "m8def.inc"
;
.EQU debug = 0
.EQU debugpulse = 0
;
; Switches for connected hardware
;
.EQU cDisplay = 1 ; LCD display connected
.EQU cDisplay8 = 0 ; displays 8 characters per line instead of 16
.EQU cDisplay2 = 1 ; two line LCD display connected
.EQU cUart = 1 ; Uart active
; attached prescaler on port C
.EQU pPresc = PORTC ; prescaler by 8 output attached to port C
.EQU pPrescD = DDRC ; data direction of prescaler
.EQU bPresc = 5 ; bit 5 enables prescaler by 8
;
; ================================================
; Other hardware depending stuff
; ================================================
;
.EQU cFreq = 16000000 ; Clock frequency processor in cycles/s
.IF cUart
.EQU cBaud = 9600 ; If Uart active, define Baudrate
.ENDIF
.EQU bLcdE = 5 ; LCD E port bit on Port B
.EQU bLcdRs = 4 ; Lcd RS port bit on Port B
;
; ================================================
; Constants for voltage measurement
; ================================================
;
; Resistor network as pre-divider for the ADC
; --------------------------------------
; R1 R2(k) Meas Accur. MaxVoltage
; kOhm kOhm Volt mV/dig Volt
; --------------------------------------
; 1000 1000 5,12 5 10
; 1000 820 5,68 6 11
; 1000 680 6,32 6 12
; 1000 560 7,13 7 14
; 1000 470 8,01 8 15
; 1000 330 10,32 10 20
; 1000 270 12,04 12 23
; 1000 220 14,20 14 27
; 1000 180 16,78 16 32
; 1000 150 19,63 19 38
; 1000 120 23,98 23 46
; 1000 100 28,16 28 55
;
.EQU cR1 = 1000 ; Resistor between ADC input and measured voltage
.EQU cR2 = 1000 ; Resistor between ADC input and ground
.EQU cRin = 8250 ; Input resistance ADC, experimental
;
; Other sSoft switches
;
.EQU cNMode = 3 ; number o0f measurements before mode changes
.EQU cDecSep = ',' ; decimal separator for numbers displayed
.EQU c1kSep = '.' ; thousands separator
.EQU nMeasm = 4 ; number of measurements per second
.IF (nMeasm<4)||(nMeasm>7)
.ERROR "Number of measurements outside acceptable range"
.ENDIF
;
; ================================================
; Hardware connections
; ================================================
; ___ ___
; RESET |1 |_| 28| Prescaler divide by 8 output
; RXD |2 A 27|
; TXD |3 T 26|
; Time inp |4 M 25|
; |5 E 24| Mode select input, 0..2.56 V
; Count in |6 L 23| Voltage input, 0..2.56 V
; VCC |7 22| GND
; GND |8 A 21| AREF (2.56 V output)
; XTAL1 |9 T 20| AVCC input
; XTAL2 |10 m 19| SCK/LCD-E
; |11 e 18| MISO/LCD-RS
; |12 g 17| MOSI/LCD-D7
; |13 a 16| LCD-D6
; LCD-D4 |14 8 15| LCD-D5
; |_________|
;
;
; ================================================
; Derived constants
; ================================================
;
.EQU cR2c = (cR2 * cRin) / (cR2+cRin)
.EQU cMultiplier = (641 * (cR1+cR2c))/cR2c ; used for voltage multiplication
.EQU cMaxVoltage = 1024*cMultiplier/256 ; in mV
.EQU cSafeVoltage = (cMaxVoltage * 5000) / 2560
.EQU cTDiv = 1000/nMeasm ; interval per measurement update
; calculating the CTC and prescaler values for TC1 (frequency measurement)
.SET cCmp1F = cFreq/32 ; CTC compare value with prescaler = 8
.SET cPre1F = (1<<WGM12)|(1<<CS11) ; CTC and prescaler = 8
.IF cFreq>2097120
.SET cCmp1F = cFreq/256 ; CTC compare value with prescaler = 64
.SET cPre1F = (1<<WGM12)|(1<<CS11)|(1<<CS10) ; prescaler = 64
.ENDIF
.IF cFreq>16776960
.SET cCmp1F = cFreq/1024 ; CTC compare value with prescaler = 256
.SET cPre1F = (1<<WGM12)|(1<<CS12) ; prescaler = 256
.ENDIF
; calculating the CTC and prescaler values for TC2 (LCD/UART update)
.SET cCmp2 = cFreq/8000
.SET cPre2 = (1<<CS21) ; prescaler = 8
.IF cFreq>2040000
.SET cCmp2 = cFreq/32000
.SET cPre2 = (1<<CS21)|(1<<CS20) ; prescaler = 32
.ENDIF
.IF cFreq>8160000
.SET cCmp2 = cFreq/64000
.SET cPre2 = (1<<CS22) ; prescaler = 64
.ENDIF
.IF cFreq>16320000
.SET cCmp2 = cFreq/128000 ; prescaler = 128
.SET cPre2 = (1<<CS22)|(1<<CS20)
.ENDIF
;
; Uart constants
;
.IF cUart
.EQU cNul = $00
.EQU cClrScr = $0C
.EQU cCr = $0D
.EQU cLf = $0A
.ENDIF
;
; Debug definitions for testing
;
;
; ================================================
; Register definitons
; ================================================
;
; R0 used for LPM and for calculation purposes
.DEF rRes1 = R1 ; Result byte 1
.DEF rRes2 = R2 ; Result byte 2
.DEF rRes3 = R3 ; Result byte 3
.DEF rRes4 = R4 ; Result byte 4
.DEF rDiv1 = R5 ; Divisor byte 1
.DEF rDiv2 = R6 ; Divisor byte 2
.DEF rDiv3 = R7 ; Divisor byte 3
.DEF rDiv4 = R8 ; Divisor byte 4
.DEF rCpy1 = R9 ; Copy byte 1
.DEF rCpy2 = R10 ; Copy byte 2
.DEF rCpy3 = R11 ; Copy byte 3
.DEF rCpy4 = R12 ; Copy byte 4
.DEF rCtr1 = R13 ; Counter/Timer byte 1
.DEF rCtr2 = R14 ; Counter/Timer byte 2
.DEF rCtr3 = R15 ; Counter/Timer byte 3
.DEF rmp = R16 ; Multipurpose register outside interrupts
.DEF rimp = R17 ; Multipurpose register inside interrupts
.DEF rSreg = R18 ; Save status register inside interrupts
.DEF rTDiv = R19 ; Internal divider for TC2 count down
.DEF rMode = R20 ; Current mode of operation
.DEF rNMode = R21 ; Number of inadequate measurements
; free: R22
.DEF rFlg = R23 ; Flag register
.EQU bCyc = 2 ; measure cycle ended
.EQU bMode = 3 ; measuring mode, 1 = frequency, 0 = time
.EQU bEdge = 4 ; measured edge, 1 = rising, 0 = falling
.EQU bOvf = 5 ; overflow bit
.EQU bAdc = 6 ; ADC conversion complete flag bit
.EQU bUartRxLine = 7 ; Uart line complete flag bit
.DEF rDelL = R24 ; delay counter for LCD, LSB
.DEF rDelH = R25 ; dto., MSB
; X = R26..R27 used for calculation purposes
; Y = R28..R29: free
; Z = R30..R31 used for LPM and calculation purposes
;
; ================================================
; SRAM definitions
; ================================================
;
.DSEG
.ORG $0060
;
; Result display space in SRAM
;
sResult:
.BYTE 32
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
;
.IF cUart
.EQU UartRxbLen = 38 ; Buffer length in bytes
;
sUartFlag: ; flag register for Uart
.BYTE 1
.EQU bUMonU = 0 ; displays voltage over Uart
.EQU bUMonF = 1 ; displays frequency over Uart
; free: bits 2..7
sUartMonUCnt: ; counter for Monitoring voltage
.BYTE 1
sUartMonURpt: ; counter preset for monitoring voltage
.BYTE 1
sUartRxBp: ; buffer pointer
.BYTE 1
sUartRxBs: ; buffer
.BYTE UartRxbLen
sUartRxBe: ; buffer end
.ENDIF
;
; Main interval timer characteristics
;
sTMeas: ; ms per measuring interval (default: 250)
.BYTE 1
;
; ADC result
;
sAdc0L: ; ADC result, channel 0, LSB
.BYTE 1
sAdc0H: ; ADC result, channel 0, MSB
.BYTE 1
sAdc1L: ; ADC result, channel 1, LSB
.BYTE 1
sAdc1H: ; ADC result, channel 1, MSB
.BYTE 1
;
; Interim storage for counter value during time measurement
;
sCtr:
.BYTE 4
;
; ================================================
; Selected mode flags
; ================================================
;
; Mode Measuring Prescale Display
; ---------------------------------------------
; 0 Frequency 8 Frequency
; 1 Frequency 1 Frequency
; 2 Time HL 1 Frequency
; 3 Time HL 1 Rounds per Minute
; 4 Time HL 1 Time
; 5 Time H 1 Time
; 6 Time L 1 Time
; 7 PW ratio H 1 Pulse width ratio H %
; 8 PW ratio L 1 Pulse width ratio L %
; 9 none - Voltage only
;
.EQU cModeFrequency8 = 0
.EQU cModeFrequency = 1
.EQU cModeTimeFreq = 2
.EQU cModeTimeRpm = 3
.EQU cModeTimeTimeHL = 4
.EQU cModeTimeTimeH = 5
.EQU cModeTimeTimeL = 6
.EQU cModeTimePwrH = 7
.EQU cModeTimePwrL = 8
.EQU cModeVoltage = 9
;
sModeSlct: ; Selected mode
.BYTE 1
sModeNext: ; next selected mode
.BYTE 1
;
;
; ==================================================
; Info on timer and counter interrupt operation
; ==================================================
;
; Clock => Presc2 => TC2 => CTC => rTDiv =>
; ADC0 conversion => ADC1 conversion => bAdc-flag
;
; Main interval timer TC2
; - uses TC2 as 8-bit-CTC, with compare interrupt
; - starts a ADC conversion
; - on ADC conversion complete:
; * store ADC result
; * convert ADC result
; * if a new counter result: convert this
; * if Uart connected and monitoring f/U: display on Uart
; * if LCD connected and display mode: display f/U result
;
; Operation at 16 MHz clock:
; cFreq => Prescaler/128 => CTC(125) => rTDiv(250)
; 16MHz => 125 kHz => 1 kHz => 4 Hz
;
; Frequeny counting modes (Mode = 0 and 1)
; - uses TC0 as 8-bit-counter to count positive edges
; - uses TC1 as 16-bit-counter to time-out the counter after 250 ms
;
; Timer modes (Mode = 2 to 8)
; - uses edge detection on external INT0 for timeout
; - uses TC1 as 16-bit-counter to time-out from edge to edge
;
; Voltage only (Mode = 9)
; - Timers TC0 and TC1 off
; - Timer TC2 times interval
;
; ==============================================
; Reset and Interrupt Vectors starting here
; ==============================================
;
.CSEG
.ORG $0000
;
; Reset/Intvectors
;
rjmp Main ; Reset
rjmp Int0Int; Int0
reti ; Int1
rjmp TC2CmpInt ; TC2 Comp
reti ; TC2 Ovf
reti ; TC1 Capt
rjmp Tc1CmpAInt ; TC1 Comp A
reti ; TC1 Comp B
rjmp Tc1OvfInt ; TC1 Ovf
rjmp TC0OvfInt ; TC0 Ovf
reti ; SPI STC
.IFDEF cUart
rjmp SioRxcIsr ; USART RX
.ELSE
reti ; USART RX
.ENDIF
reti ; USART UDRE
reti ; USART TXC
rjmp AdcCcInt ; ADC Conv Compl
reti ; EERDY
reti ; ANA_COMP
reti ; TWI
reti ; SPM_RDY
;
; =============================================
;
; Interrupt Service Routines
;
; =============================================
;
; TC2 Compare Match Interrupt
; counts rTDiv down, if zero: starts an AD conversion
;
TC2CmpInt:
in rSreg,SREG ; save SREG
dec rTDiv ; count down
brne TC2CmpInt1 ; not zero, interval not ended
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start ADC conversion
lds rTDiv,sTMeas ; restart interval timer
TC2CmpInt1:
out SREG,rSreg ; restore SREG
reti
;
; External Interrupt INT0 Service Routine
; active in modes 2 to 6 (measuring the signal duration),
; detects positive going edges of the input
; INT1, TC1 is in free running mode,
; reads the current counter state of TC1,
; copies it to the result registers,
; clears the counter and restarts it
;
Int0Int:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp Int0Int1 ; 4, no, last result hasn't been read
in rCpy1,TCNT1L ; 4, read timer 1 LSB
in rCpy2,TCNT1H ; 5, dto., MSB
mov rCpy3,rCtr2 ; 6, copy the counter bytes
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
cbr rFlg,1<<bEdge ; 9, set falling edge
sbic PIND,2 ; 10/11, check if input = 0
sbr rFlg,1<<bEdge ; 11, no, set edge flag to rising
Int0Int1: ; 4/11
ldi rimp,0 ; 5/12, reset the timer
out TCNT1H,rimp ; 6/13, set TC1 zero to restart
out TCNT1L,rimp ; 7/14
mov rCtr1,rimp ; 8/15, clear the upper bytes
mov rCtr2,rimp ; 9/16
mov rCtr3,rimp ; 10/17
out SREG,rSreg ; 11/18, restore SREG
reti ; 15/22
;
; TC1 Compare Match A Interrupt Service Routine
; active in modes 0 and 1 (measuring the number of
; sigals on the T1 input), timeout every 0.25s,
; reads the counter TC0, copies the count to
; the result registers and clears TC0
;
Tc1CmpAInt:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp TC1CmpAInt1 ; 4, no, last result hasn't been read
in rCpy1,TCNT0 ; 4, read counter TC0
mov rCpy2,rCtr1 ; 5, copy counter bytes to result
mov rCpy3,rCtr2 ; 6
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
Tc1CmpAInt1: ; 4/8
ldi rimp,0 ; 5/9, clear counter
out TCNT0,rimp ; 6/10
mov rCtr1,rimp ; 7/11, clear counter bytes
mov rCtr2,rimp ; 8/12
mov rCtr3,rimp ; 9/13
out SREG,rSreg ; 10/14, restore SREG
reti ; 14/18
;
; TC1 Overflow Interrupt Service Routine
; active in modes 2 to 6 counting clock cycles to measure time
; increases the upper bytes and detects overflows
;
Tc1OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr2 ; 2, increase byte 3 of the counter
brne Tc1OvfInt1 ; 3/4, no overflow
inc rCtr3 ; 4, increase byte 4 of the counter
brne Tc1OvfInt1 ; 5/6, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 6, set overflow and end of cycle bit
Tc1OvfInt1: ; 4/6
out SREG,rSreg ; 5/7, restore SREG
reti ; 9/11
;
; TC0 Overflow Interrupt Service Routine
; active in modes 0 and 1 counting positive edges on T1
; increases the upper bytes and detects overflows
;
Tc0OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr1 ; 2, increase byte 2 of the counter
brne Tc0OvfInt1 ; 3/4, no overflow
inc rCtr2 ; 4, increase byte 3 of the counter
brne Tc0OvfInt1 ; 5/6, no overflow
inc rCtr3 ; 6, increase byte 4 of the counter
brne Tc0OvfInt1 ; 7/8, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 8, set overflow bit
Tc0OvfInt1: ; 4/6/8
out SREG,rSreg ; 5/7/9, restore SREG
reti ; 9/11/13
;
; Uart RxC Interrupt Service Routine
; receives a character, signals errors, echoes it back,
; puts it into the SRAM line buffer, checks for carriage
; return characters, if yes echoes additional linefeed
; and sets line-complete flag
;
.IF cUart
SioRxCIsr:
in rSreg,SREG ; 1, Save SReg
in rimp,UCSRA ; 2, Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; 3, isolate error bits
in rimp,UDR ; 4, read character from UART
breq SioRxCIsr1 ; 5/6, no errors
ldi rimp,'*' ; 6, signal an error
out UDR,rimp ; 7
rjmp SioRxCIsr4 ; 9, return from int
SioRxCIsr1: ; 6
out UDR,rimp ; 7, echo the character
push ZH ; 9, Save Z register
push ZL ; 11
ldi ZH,HIGH(sUartRxBs) ; 12, Load Position for next RX char
lds ZL,sUartRxBp ; 14
st Z+,rimp ; 16, save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; 17, End of buffer?
brcc SioRxCIsr2 ; 18/19, Buffer overflow
sts sUartRxBp,ZL ; 20, Save next pointer position
SioRxCIsr2: ; 19/20
cpi rimp,cCr ; 20/21, Carriage Return?
brne SioRxCIsr3 ; 21/22/23, No, go on
ldi rimp,cLf ; 22/23, Echo linefeed
out UDR,rimp ; 23/24
sbr rFlg,(1<<bUartRxLine) ; 24/25, Set line complete flag
SioRxCIsr3: ; 22/23/24/25
pop ZL ; 24/25/26/27, restore Z-register
pop ZH ; 26/27/28/29
SioRxCIsr4: ; 9/26/27/28/29
out SREG,rSreg ; 10/27/28/29/30, restore SREG
reti ; 14/31/32/33/34, return from Int
.ENDIF
;
; ADC has completed a conversion
; used in all modes, ADC has completed a conversion
; if ADMUX channel is 0 then set ADMUX=1 and start
; another coversion
; if ADMUX channel is 1 he set ADMUX=0, disable the ADC
; and set teh ADC cycle end flag
;
.EQU cStopAdc = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
.EQU cStartAdc = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|cStopAdc
AdcCcInt:
in rSreg,SREG ; 1, save SREG
in rimp,ADMUX ; 2, read the current channel info
sbrc rimp,0 ; 3/4, jump if channel = 0
rjmp AdcCcInt1 ; 5
sbr rimp,1 ; 5, set channel MUX to one
out ADMUX,rimp ; 6
in rimp,ADCL ; 7, read result LSB
sts sAdc0L,rimp ; 9, store result LSB
in rimp,ADCH ; 10, read result MSB
sts sAdc0H,rimp ; 12, store result MSB
ldi rimp,cStartAdc
out ADCSRA,rimp ; 14, start next conversion
out SREG,rSreg ; 15, restore SREG
reti ; 19
AdcCcInt1: ; 5
cbr rimp,1 ; 6, set MUX to channel 0
out ADMUX,rimp ; 7
in rimp,ADCL ; 8, read result LSB
sts sAdc1L,rimp ; 10, store result LSB
in rimp,ADCH ; 11, read result MSB
sts sAdc1H,rimp ; 13, store result MSB
sbr rFlg,1<<bAdc ; 14, set flag bit
ldi rimp,cStopAdc ; 15, ADC off
out ADCSRA,rimp ; 16, switch ADC off
out SREG,rSreg ; 17, restore SREG
reti ; 21
;
; ================================================
; Common subroutines
; ================================================
;
; Setting timer/counter modes for measuring
;
SetModeNext:
rcall ClrTc ; clear the timers TC0 and TC1, disable INT0
lds rmp,sModeNext ; read next mode
cpi rmp,10 ; check number of modes
brcs SetModeNext1 ; mode is ok
ldi rmp,1 ; set mode 1
sts sModeNext,rmp ; correct next mode
SetModeNext1:
mov rMode,rmp ; copy to current mode
ldi ZH,HIGH(SetModeTab)
ldi ZL,LOW(SetModeTab)
add ZL,rmp
ldi rmp,0
adc ZH,rmp
ijmp
; Table mode setting
SetModeTab:
rjmp SetMode0 ; f div 8, f
rjmp SetModeF ; f, f
rjmp SetModeT ; t, f
rjmp SetModeT ; t, u
rjmp SetModeT ; t, t
rjmp SetmodeE ; th, t
rjmp SetModeE ; tl, t
rjmp SetModeE ; th, p
rjmp SetModeE ; tl, p
ret ; U, U
;
; Set counters/timers to mode 0
; TC0 counts input signals (positive edges)
; TC1 times the gate at 250 ms
; INT0 disabled
;
SetMode0:
cbi pPresc,bPresc ; enable prescaler
rjmp SetModeF ; frequency measurement
;
; Set counters/timers to mode 1
;
SetMode1:
sbi pPresc,bPresc ; disable prescaler
; Set timer/counter mode to frequency measurement
SetModeF:
ldi rmp,HIGH(cCmp1F) ; set the compare match high value
out OCR1AH,rmp
ldi rmp,LOW(cCmp1F) ; set the compare match low value
out OCR1AL,rmp
ldi rmp,0xFF ; disable the compare match B
out OCR1BH,rmp
out OCR1BL,rmp
ldi rmp,0 ; CTC mode
out TCCR1A,rmp
ldi rmp,cPre1F ; set the prescaler value for TC1
out TCCR1B,rmp
ldi rmp,(1<<CS02)|(1<<CS01)|(1<<CS00) ; count rising edges on T0
out TCCR0,rmp
ldi rmp,(1<<OCIE2)|(1<<OCIE1A)|(1<<TOIE0) ; enable TC2Cmp, TC1CmpAInt and
TC0OverflowInt
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement
;
SetModeT:
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00) ; sleep enable, positive edges on INT0 interrupt
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement, all edges
;
SetModeE:
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC00) ; sleep enable, any logical change on INT0 interrupts
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
;
; clears the timers and resets the upper bytes
;
ClrTc:
clr rmp ; disable INT0
out GICR,rmp
clr rmp ; stop the counters/timers
out TCCR0,rmp ; stop TC0 counting/timing
out TCCR1B,rmp ; stop TC1 counting/timing
out TCNT0,rmp ; clear TC0
out TCNT1L,rmp ; clear TC1
out TCNT1H,rmp
clr rCtr1 ; clear upper bytes
clr rCtr2
clr rCtr3
ldi rmp,1<<OCIE2 ; enable only output compare of TC2 ints
out TIMSK,rmp ; timer int disable
ret
;
; =======================================================
; Math routines
; =======================================================
;
; Divides cFreq/256 by the timer value in rDiv4:rDiv3:rDiv2:rDiv1
; yields frequency in R4:R3:R2:(Fract):R1
;
Divide:
clr rmp ; rmp:R0:ZH:ZL:XH:XL is divisor
clr R0
clr ZH
ldi ZL,BYTE3(cFreq/256) ; set divisor
ldi XH,BYTE2(cFreq/256)
ldi XL,BYTE1(cFreq/256)
clr rRes1 ; set result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
Divide1:
lsl XL ; multiply divisor by 2
rol XH
rol ZL
rol ZH
rol R0
rol rmp
cp ZL,rDiv1 ; compare with divident
cpc ZH,rDiv2
cpc R0,rDiv3
cpc rmp,rDiv4
brcs Divide2
sub ZL,rDiv1
sbc ZH,rDiv2
sbc R0,rDiv3
sbc rmp,rDiv4
sec
rjmp Divide3
Divide2:
clc
Divide3:
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc Divide1
ret
;
; Multiply measured time in rRes4:rRes3:rRes2:rRes1 by 65536 / fq(MHz)
; rmp:R0 are the upper bytes of the input
; ZH:ZL:rDiv4:rDiv3:rDiv2:rDiv1 is the interim result
; XH:XL is the multiplicator
; result is in rRes4:rRes3:rRes2:rRes1
;
.EQU cMulti = 65536000 / (cFreq/1000)
;
Multiply:
ldi XH,HIGH(cMulti) ; set multiplicator
ldi XL,LOW(cMulti)
clr ZH
clr ZL
clr rDiv4
clr rDiv3
clr rDiv2
clr rDiv1
clr R0
clr rmp
Multiply1:
cpi XL,0
brne Multiply2
cpi XH,0
breq Multiply4
Multiply2:
lsr XH
ror XL
brcc Multiply3
add rDiv1,rRes1
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
adc ZL,R0
adc ZH,rmp
Multiply3:
lsl rRes1
rol rRes2
rol rRes3
rol rRes4
rol R0
rol rmp
rjmp Multiply1
Multiply4:
ldi rmp,128 ; round result
clr R0
add rDiv2,rmp
adc rDiv3,R0
adc rDiv4,R0
adc ZL,R0
adc ZH,R0
mov rRes1,rDiv3 ; move result
mov rRes2,rDiv4
mov rRes3,ZL
mov rRes4,ZH
ret
;
; Display seconds at buffer end
;
DisplSec:
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'u'
st X+,rmp
ldi rmp,'s'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ret
;
; An overflow has occurred during pulse width calculation
;
PulseOvflw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
st X+,rmp
.IF cDisplay8
ldi ZH,HIGH(2*TxtPOvflw8)
ldi ZL,LOW(2*TxtPOvflw8)
ldi rmp,7
.ELSE
ldi ZH,HIGH(2*TxtPOvflw16)
ldi ZL,LOW(2*TxtPOvflw16)
ldi rmp,15
.ENDIF
PulseOvflw1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne PulseOvflw1
ret
.IF cDisplay8
TxtPOvflw8:
.DB ":error! "
.ELSE
TxtPOvflw16:
.DB ":error calcul.! "
.ENDIF
;
; ======================================================
; Pulse width calculations
; ======================================================
;
; Calculate the pulse width ratio
; active cycle time is in rDelH:rDelL:R0:rmp
; total cycle time is in rDiv
; result will be in rRes
; overflow: carry flag is set
;
CalcPwO: ; overflow
sec
ret
CalcPw:
mov rRes1,rmp ; copy active cycle time to rRes
mov rRes2,R0
mov rRes3,rDelL
mov rRes4,rDelH
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
mov XL,rRes1 ; copy to Z:X
mov XH,rRes2
mov ZL,rRes3
mov ZH,rRes4
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO
add rRes1,XL ; * 24
adc rRes2,XH
adc rRes3,ZL
adc rRes4,ZH
clr ZH ; clear the four MSBs of divisor
clr ZL
clr XH
mov XL,rDelH ; * 256
mov rDelH,rDelL
mov rDelL,R0
mov R0,rmp
clr rmp
lsl R0 ; * 512
rol rDelL
rol rDelH
rol XL
rol XH
lsl R0 ; * 1024
rol rDelL
rol rDelH
rol XL
rol XH
sub rmp,rRes1 ; * 1000
sbc R0,rRes2
sbc rDelL,rRes3
sbc rDelH,rRes4
sbc XL,ZH
sbc XH,ZH

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm (1 of 3)1/20/2009 7:51:44 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm

cp XL,rDiv1 ; overflow?
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcc CalcPwO
clr rRes1 ; clear result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
CalcPw1: ; dividing loop
lsl rmp ; multiply by 2
rol R0
rol rDelL
rol rDelH
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1 ; compare with divisor
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw2 ; smaller, roll zero in
sub XL,rDiv1 ; subtract divisor
sbc XH,rDiv2
sbc ZL,rDiv3
sbc ZH,rDiv4
sec ; roll one in
rjmp CalcPw3
CalcPw2:
clc
CalcPw3: ; roll result
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc CalcPw1 ; roll on
lsl rDelL ; round result
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw4
ldi rmp,1 ; round up
add rRes1,rmp
ldi rmp,0
adc rRes2,rmp
adc rRes3,rmp
adc rRes4,rmp
CalcPw4:
tst rRes4 ; check > 1000
brne CalcPwE
tst rRes3
brne CalcPwE
ldi rmp,LOW(1001)
cp rRes1,rmp
ldi rmp,HIGH(1001)
cpc rRes2,rmp
brcc CalcPwE
clc ; no error
ret
CalcPwE: ; error
sec
ret
;
; Display the binary in R2:R1 in the form " 100,0%"
;
DisplPw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
ldi rmp,' '
st X+,rmp
st X+,rmp
clr R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecX2
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall DisplDecX2
ldi ZL,10
inc R0
rcall DisplDecX2
ldi rmp,cDecSep
st X+,rmp
ldi rmp,'0'
add rmp,rRes1
st X+,rmp
ldi rmp,'%'
st X+,rmp
.IF ! cDisplay8
ldi rmp,8
ldi ZL,' '
DisplPw1:
st X+,ZL
dec rmp
brne DisplPw1
.ENDIF
ret
;
; If the first characters in the result buffer are empty,
; place the character in ZL here and add equal, if possible
;
DisplMode:
ldi XH,HIGH(sResult+1) ; point to result buffer
ldi XL,LOW(sResult+1)
ld rmp,X ; read second char
cpi rmp,' '
brne DisplMode1
ldi rmp,'='
st X,rmp
DisplMode1:
sbiw XL,1
ld rmp,X ; read first char
cpi rmp,' '
brne DisplMode2
st X,ZL
DisplMode2:
ret
;
;=================================================
; Display binary numbers as decimal
;=================================================
;
; Converts a binary in R2:R1 to a digit in X
; binary in Z
;
DecConv:
clr rmp
DecConv1:
cp R1,ZL ; smaller than binary digit?
cpc R2,ZH
brcs DecConv2 ; ended subtraction
sub R1,ZL
sbc R2,ZH
inc rmp
rjmp DecConv1
DecConv2:
tst rmp
brne DecConv3
tst R0
brne DecConv3
ldi rmp,' ' ; suppress leading zero
rjmp DecConv4
DecConv3:
subi rmp,-'0'
DecConv4:
st X+,rmp
ret
;
; Display fractional number in R3:R2:(Fract)R1
;
DisplFrac:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
.ENDIF
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DisplDecY2
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecY2
.IF ! cDisplay8
ldi rmp,c1kSep
tst R0
brne DisplFrac0
ldi rmp,' '
DisplFrac0:
st X+,rmp
.ENDIF
ldi ZL,100
rcall DisplDecY1
ldi ZL,10
rcall DisplDecY1
ldi rmp,'0'
add rmp,R2
st X+,rmp
tst R1 ; fraction = 0?
brne DisplFrac1
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
st X+,rmp
st X+,rmp
.ENDIF
ret
DisplFrac1:
ldi rmp,cDecSep
st X+,rmp
.IF cDisplay8
ldi ZL,2
.ELSE
ldi ZL,3
.ENDIF
DisplFrac2:
clr rRes3
clr rRes2
mov R0,rRes1 ; * 1
lsl rRes1 ; * 2
adc rRes2,rRes3
lsl rRes1 ; * 4
rol rRes2
add rRes1,R0 ; * 5
adc rRes2,rRes3
lsl rRes1 ; * 10
rol rRes2
ldi rmp,'0'
add rmp,rRes2
st X+,rmp
dec ZL
brne DisplFrac2
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X+,rmp
.ENDIF
ret
;
; convert a decimal in R4:R3:R2, decimal in ZH:ZL
;
DisplDecY2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY2a:
cp rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecY2b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecY2a
DisplDecY2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY2c
ldi rmp,' '
DisplDecY2c:
st X+,rmp
ret
;
; convert a decimal decimal in R:R2, decimal in ZL
;
DisplDecY1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY1a:
cp rRes2,ZL
cpc rRes3,rDiv2
brcs DisplDecY1b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecY1a
DisplDecY1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY1c
ldi rmp,' '
DisplDecY1c:
st X+,rmp
ret
;
; Display a 4-byte-binary in decimal format on result line 1
; 8-bit-display: "12345678"
; 16-bit-display: " 12.345.678 Hz "
;
Displ4Dec:
ldi rmp,BYTE1(100000000) ; check overflow
cp rRes1,rmp
ldi rmp,BYTE2(100000000)
cpc rRes2,rmp
ldi rmp,BYTE3(100000000)
cpc rRes3,rmp
ldi rmp,BYTE4(100000000)
cpc rRes4,rmp
brcs Displ4Dec1
rjmp CycleOvf
Displ4Dec1:
clr R0 ; suppress leading zeroes
ldi XH,HIGH(sResult) ; X to result buffer
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' ' ; clear the first two digits
st X+,rmp
st X+,rmp
.ENDIF
ldi ZH,BYTE3(10000000) ; 10 mio
ldi ZL,BYTE2(10000000)
ldi rmp,BYTE1(10000000)
rcall DisplDecX3
ldi ZH,BYTE3(1000000) ; 1 mio
ldi ZL,BYTE2(1000000)
ldi rmp,BYTE1(1000000)
rcall DisplDecX3
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec2
ldi rmp,' '
Displ4Dec2:
st X+,rmp
.ENDIF
ldi ZH,BYTE3(100000) ; 100 k
ldi ZL,BYTE2(100000)
ldi rmp,BYTE1(100000)
rcall DisplDecX3
ldi ZH,HIGH(10000) ; 10 k
ldi ZL,LOW(10000)
rcall DisplDecX2
ldi ZH,HIGH(1000) ; 1 k
ldi ZL,LOW(1000)
rcall DisplDecX2
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec3
ldi rmp,' '
Displ4Dec3:
st X+,rmp
.ENDIF
ldi ZL,100 ; 100
rcall DisplDecX1
ldi ZL,10
rcall DisplDecX1
ldi rmp,'0' ; 1
add rmp,R1
st X+,rmp
ret
;
; convert a decimal in R3:R2:R1, decimal in ZH:ZL:rmp
;
DisplDecX3:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; subtractor for byte 4
DisplDecX3a:
cp rRes1,rmp ; compare
cpc rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecX3b ; ended
sub rRes1,rmp ; subtract
sbc rRes2,ZL
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecX3a
DisplDecX3b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX3c
ldi rmp,' '
DisplDecX3c:
st X+,rmp
ret
;
; convert a decimal in R3:R2:R1, decimal in ZH:ZL
;
DisplDecX2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX2a:
cp rRes1,ZL
cpc rRes2,ZH
cpc rRes3,rDiv2
brcs DisplDecX2b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,ZH
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecX2a
DisplDecX2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX2c
ldi rmp,' '
DisplDecX2c:
st X+,rmp
ret
;
; convert a decimal decimal in R2:R1, decimal in ZL
;
DisplDecX1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX1a:
cp rRes1,ZL
cpc rRes2,rDiv2
brcs DisplDecX1b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,rDiv2
inc rDiv1
rjmp DisplDecX1a
DisplDecX1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX1c
ldi rmp,' '
DisplDecX1c:
st X+,rmp
ret
;
;=================================================
; Delay routines
;=================================================
;
Delay10ms:
ldi rDelH,HIGH(10000)
ldi rDelL,LOW(10000)
rjmp DelayZ
Delay15ms:
ldi rDelH,HIGH(15000)
ldi rDelL,LOW(15000)
rjmp DelayZ
Delay4_1ms:
ldi rDelH,HIGH(4100)
ldi rDelL,LOW(4100)
rjmp DelayZ
Delay1_64ms:
ldi rDelH,HIGH(1640)
ldi rDelL,LOW(1640)
rjmp DelayZ
Delay100us:
clr rDelH
ldi rDelL,100
rjmp DelayZ
Delay40us:
clr rDelH
ldi rDelL,40
rjmp DelayZ
;
; Delays execution for Z microseconds
;
DelayZ:
.IF cFreq>18000000
nop
nop
.ENDIF
.IF cFreq>16000000
nop
nop
.ENDIF
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
sbiw rDelL,1 ; 2
brne DelayZ ; 2
ret
;
; =========================================
; Main Program Start
; =========================================
;
main:
ldi rmp,HIGH(RAMEND) ; set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
clr rFlg ; set flags to default
;
.IF debug
.EQU number = 100000000
ldi rmp,BYTE4(number)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(number)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(number)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(number)
mov rRes1,rmp
mov rDiv1,rmp
rcall CycleM6
beloop: rjmp beloop
.ENDIF
.IF debugpulse
.EQU nhigh = 100000000
.EQU nlow = 15000
ldi rmp,BYTE4(nhigh)
sts sCtr+3,rmp
ldi rmp,BYTE3(nhigh)
sts sCtr+2,rmp
ldi rmp,BYTE2(nhigh)
sts sCtr+1,rmp
ldi rmp,BYTE1(nhigh)
sts sCtr,rmp
ldi rmp,BYTE4(nlow)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(nlow)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(nlow)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(nlow)
mov rRes1,rmp
mov rDiv1,rmp
sbr rFlg,1<<bEdge
rcall CycleM7
bploop: rjmp bploop
.ENDIF
;
; Clear the output storage
;
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,' '
mov R0,rmp
ldi rmp,32
main1:
st Z+,R0
dec rmp
brne main1
;
; Init the Uart
;
.IF cUart
rcall UartInit
ldi rmp,1<<bUMonU ; monitor U over Uart
sts sUartFlag,rmp
ldi rmp,20 ; 5 seconds
sts sUartMonURpt,rmp ; set repeat default value
ldi rmp,1
sts sUartMonUCnt,rmp
.ENDIF
;
; Init the LCD
;
.IF cDisplay
rcall LcdInit
.ENDIF
;
; Disable the Analog comparator
;
ldi rmp,1<<ACD
out ACSR,rmp
;
; Disable the external prescaler by 8
;
sbi pPrescD,bPresc ; set prescaler port bit to output
sbi pPresc,bPresc ; disable the prescaler
;
; Init the ADC
;
ldi rmp,(1<<REFS1)|(1<<REFS0) ; int.ref, channel 0
out ADMUX,rmp
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; prescaler = 128
out ADCSRA,rmp
;
; Start main interval timer
;
ldi rmp,cCmp2 ; set Compare Match
out OCR2,rmp
ldi rmp,cPre2|(1<<WGM21) ; CTC mode and prescaler
out TCCR2,rmp
;
; Start timer/counter TC2 interrupts
;
ldi rmp,(1<<OCIE2) ; Interrupt mask
out TIMSK,rmp
;
; Set initial mode to mode 1
;
ldi rmp,1 ; initial mode = 1
sts sModeNext,rmp
rcall SetModeNext
;
sei ; enable interrupts
;
loop:
sleep ; send CPU to sleep
nop
sbrc rFlg,bCyc ; check cycle end
rcall Cycle
sbrc rFlg,bAdc
rcall Interval
.IF cUart
sbrc rFlg,bUartRxLine ; check line complete
rcall UartRxLine ; call line complete
.ENDIF
rjmp loop ; go to sleep
;
; Timer interval for calculation and display
;
Interval:
cbr rFlg,1<<bAdc ; clear flag
lds ZL,sAdc1L ; read ADC channel 1 value
lds ZH,sAdc1H
lsl ZL ; multiply by 2
rol ZH
subi ZH,-2
cpi ZH,cModeTimeRpm ; check if new mode to be set
brcs Interval1
sts sModeNext,ZH ; selected mode is not frequency, set
rjmp Interval2
Interval1: ; selected mode is frequency
lds rmp,sModeNext ; read next mode
cpi rmp,cModeTimeRpm
brcs Interval2 ; frequency already selected
ldi rmp,cModeFrequency
sts sModeNext,rmp
Interval2:
lds rmp,sModeNext ; check if mode has to be changed
cp rMode,rmp
breq Interval3 ; continue current mode
rcall SetModeNext ; start new mode
Interval3:
.IF cUart || cDisplay
lds R0,sAdc0L ; read ADC value
lds R1,sAdc0H
rcall cAdc2U ; convert to text
.IF cDisplay
rcall LcdDisplayFT
rcall LcdDisplayU
.ENDIF
.IF cUart
rcall UartMonU
.ENDIF
.ENDIF
ret
;
; Frequency/Time measuring cycle ended, calculate results
;
Cycle:
sbrc rFlg,bOvf ; check overflow
rjmp CycleOvf ; jump to overflow
mov rRes1,rCpy1 ; copy counter
mov rRes2,rCpy2
mov rRes3,rCpy3
mov rRes4,rCpy4
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
mov rDiv1,rRes1 ; copy again
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
ldi ZH,HIGH(CycleTab) ; point to mode table
ldi ZL,LOW(CycleTab)
add ZL,rMode ; displace table by mode
brcc Cycle1
inc ZH
Cycle1:
ijmp ; call the calculation routine
; overflow occurred
CycleOvf:
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
ldi XH,HIGH(sResult) ; point to result buffer
ldi XL,LOW(sResult)
.IF cDisplay8
ldi ZH,HIGH(2*TxtOvf8) ; point to short message
ldi ZL,LOW(2*TxtOvf8)
ldi rmp,8
.ELSE
ldi ZH,HIGH(2*TxtOvf16) ; point to long message
ldi ZL,LOW(2*TxtOvf16)
ldi rmp,16
.ENDIF
CycleOvf1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne CycleOvf1
ret
;
.IF cDisplay8
TxtOvf8:
.DB " ovflow"
.ELSE
TxtOvf16:
.DB " overflow "
.ENDIF
; Table with routines for the 8 modes
CycleTab:
rjmp CycleM0
rjmp CycleM1
rjmp CycleM2
rjmp CycleM3
rjmp CycleM4
rjmp CycleM5
rjmp CycleM6
rjmp CycleM7
rjmp CycleM8
ret ; voltage only
;
; Mode 0: Measured prescaled frequency, display frequency
;
CycleM0:
mov rmp,rRes3 ; check frequency below 2 MHz
or rmp,rRes4
brne CycleM0a
dec rNMode ; count mode counter down
brne CycleM0a
ldi rNMode,cNMode ; restart mode counter
ldi rmp,1 ; switch to mode 1
sts sModeNext,rmp
CycleM0a:
clr R5 ; detect overflow in R5
lsl R1 ; * 2
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 4
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 8
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 16
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 32
rol R2
rol R3
rol R4
rol R5
tst R5 ; check overflow
breq CycleM0b ; no error
rjmp CycleOvf
CycleM0b:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'F'
rjmp DisplMode
;
; Mode 1: Frequency measured, prescale = 1, display frequency
;
CycleM1:
ldi rmp,0 ; switch to mode 0?
tst rRes4
brne CycleM1a ; switch to mode 0
mov rmp,rRes3
cpi rmp,0x26 ; compare > 10 MHz
ldi rmp,0
brcc CycleM1a
tst rRes3 ; check smaller than 1 kHz
brne CycleM1b
tst rRes2
brne CycleM1b
ldi rmp,2 ; switch to mode 2
CycleM1a:
dec rNMode ; count modes
brne CycleM1b
ldi rNMode,cNMode
sts sModeNext,rmp
CycleM1b:
clr rDiv1 ; detect overflow in rDiv1
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
tst rDiv1 ; check overflow
breq CycleM1d ; no error
rjmp CycleOvf
CycleM1d:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'f'
rjmp DisplMode
;
; Mode 2: Time measured, prescale = 1, display frequency
;
CycleM2:
mov rmp,rDiv2 ; check too small
andi rmp,0xC0 ; isolate upper six bits
or rmp,rDiv3

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm (2 of 3)1/20/2009 7:51:44 PM


http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm

or rmp,rDiv4
brne CycleM2a
dec rNMode ; count mode change counter down
brne CycleM2a
ldi rNMode,cNMode ; restart counter
ldi rmp,cModeFrequency ; switch to frequency mode
sts sModeNext,rmp
CycleM2a:
rcall Divide
tst rRes4
brne CycleM2e
rcall DisplFrac
ldi ZL,'v'
rcall DisplMode
ret
CycleM2e:
mov rRes1,rRes2 ; number too big, skip fraction
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'v'
rcall DisplMode
ret
;
; Measure time, display rounds per minute
;
CycleM3:
rcall Divide
clr R0 ; overflow detection
clr rmp
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
mov rDiv1,rRes1 ; copy
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 32
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 64
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
tst R0 ; overflow?
breq CycleM3a
rjmp CycleOvf
CycleM3a:
sub rRes1,rDiv1
sbc rRes2,rDiv2
sbc rRes3,rDiv3
sbc rRes4,rDiv4
mov rRes1,rRes2
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'r'
st X+,rmp
ldi rmp,'p'
st X+,rmp
ldi rmp,'m'
st X+,rmp
.ENDIF
ldi ZL,'u'
rcall DisplMode
ret
;
; Measure time high+low, display time
;
CycleM4:
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'t'
rcall DisplMode
ret
;
; Measure time high, display time
;
CycleM5:
sbrs rFlg,bEdge
rjmp CycleM5a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'h'
rcall DisplMode
CycleM5a:
ret
;
; Measure time low, display time
;
CycleM6:
sbrc rFlg,bEdge
rjmp CycleM6a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'l'
rcall DisplMode
CycleM6a:
ret
;
; Measure time high and low, display pulse width ratio high in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active high time
;
CycleM7:
sbrs rFlg,bEdge
rjmp CycleM7a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rRes1,Z+ ; copy counter value
ld rRes2,Z+
ld rRes3,Z+
ld rRes4,Z+
add rDiv1,rRes1 ; add to total time
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
brcs CycleM7b
mov rmp,rRes1 ; copy high value to divisor
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM7b ; error
rcall DisplPw ; display the ratio
ldi ZL,'P'
rjmp DisplMode
CycleM7a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM7b: ; overflow
ldi rmp,'P'
rjmp PulseOvFlw
;
; Measure time high and low, display pulse width ratio low in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active low time
;
CycleM8:
sbrs rFlg,bEdge
rjmp CycleM8a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rmp,Z+ ; read high-time
ld R0,Z+
ld rDelL,Z+
ld rDelH,Z
add rDiv1,rmp ; add to total time
adc rDiv2,R0
adc rDiv3,rDelL
adc rDiv4,rDelH
mov rmp,rRes1 ; copy the active low time
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM8b ; error
rcall DisplPw ; display the ratio
ldi ZL,'p'
rjmp DisplMode
CycleM8a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM8b: ; overflow
ldi rmp,'p'
rjmp PulseOvFlw
;
; Converts an ADC value in R1:R0 to a voltage for display
; cAdc2U input: ADC value, output: Voltage in V for display
;
cAdc2U:
clr R2 ; clear the registers for left shift in R3:R2
clr R3
ldi rmp,HIGH(cMultiplier) ; Multiplier to R5:R4
mov R5,rmp
ldi rmp,LOW(cMultiplier)
mov R4,rmp
clr XL ; clear result in ZH:ZL:XH:XL
clr XH
clr ZL
clr ZH
cAdc2U1:
lsr R5 ; shift Multiplier right
ror R4
brcc cAdc2U2 ; bit is zero, don't add
add XL,R0 ; add to result
adc XH,R1
adc ZL,R2
adc ZH,R3
cAdc2U2:
mov rmp,R4 ; check zero
or rmp,R5
breq cAdc2U3 ; end of multiplication
lsl R0 ; multiply by 2
rol R1
rol R2
rol R3
rjmp cAdc2U1 ; go on multipying
cAdc2U3:
ldi rmp,$80 ; round up
add XL,rmp
ldi rmp,$00
adc XH,rmp
adc ZL,rmp
adc ZH,rmp
tst ZH ; check overflow
mov R1,XH ; copy result to R2:R1
mov R2,ZL
ldi XH,HIGH(sResult+16) ; point to result
ldi XL,LOW(sResult+16)
ldi rmp,'U'
st X+,rmp
breq cAdc2U5
ldi ZH,HIGH(2*AdcErrTxt)
ldi ZL,LOW(2*AdcErrTxt)
cAdc2U4:
lpm
tst R0
breq cAdc2U6
sbiw ZL,1
st X+,R0
rjmp cAdc2U4
cAdc2U5:
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DecConv
inc R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DecConv
ldi rmp,cDecSep
st X+,rmp
clr ZH
ldi ZL,100
rcall DecConv
ldi ZL,10
rcall DecConv
ldi rmp,'0'
add rmp,R1
st X+,rmp
ldi rmp,'V'
st X,rmp
lds rmp,sResult+17
cpi rmp,' '
brne cAdc2U6
ldi rmp,'='
sts sResult+17,rmp
cAdc2U6:
ret
;
AdcErrTxt:
.DB "overflw",$00
;
; ===========================================
; Lcd display routines
; ===========================================
;
.IF cDisplay ; if display connected
;
; LcdE pulses the E output for at least 1 us
;
LcdE:
sbi PORTB,bLcdE
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
.IF cFreq>2000000
nop
nop
.ENDIF
nop
nop
cbi PORTB,bLcdE
ret
;
; outputs the content of rmp (temporary
; 8-Bit-Interface during startup)
;
LcdRs8:
out PORTB,rmp
rcall LcdE
ret
;
; write rmp as 4-bit-command to the LCD
;
LcdRs4:
mov R0,rmp ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original back
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE
mov rmp,R0 ; restore rmp
ret
;
; write rmp as data over 4-bit-interface to the LCD
;
LcdData4:
push rmp ; save rmp
mov rmp,R0 ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original again
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE
rcall Delay40us
pop rmp ; restore rmp
ret
;
; writes the text in flash to the LCD, number of
; characters in rmp
;
LcdText:
lpm ; read character from flash
adiw ZL,1
rcall LcdData4 ; write to
rcall delay40us
dec rmp
brne LcdText
ret
;
; Inits the LCD with a 4-bit-interface
;
LcdInit:
ldi rmp,0x0F | (1<<bLcdE) | (1<<bLcdRs)
out DDRB,rmp
clr rmp
out PORTB,rmp
rcall delay15ms ; wait for complete self-init
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay4_1ms ; wait for 4.1 ms
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay100us ; wait for 100 us
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay40us ; delay 40 us
ldi rmp,0x02 ; Function set 4-bit-interface
rcall LcdRs8
rcall delay40us
.IF cDisplay2
ldi rmp,0x28 ; 4-bit-interface, two line display
.ELSE
ldi rmp,0x20 ; 4-bit-interface, single line display
.ENDIF
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x08 ; display off
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x01 ; display clear
rcall LcdRs4
rcall delay1_64ms ; delay 1.64 ms
ldi rmp,0x06 ; increment, don't shift
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x0C ; display on
rcall LcdRs4
rcall delay40us
ldi rmp,0x80 ; position on line 1
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
ldi ZH,HIGH(2*LcdInitTxt8)
ldi ZL,LOW(2*LcdInitTxt8)
.ELSE
ldi rmp,16
ldi ZH,HIGH(2*LcdInitTxt16)
ldi ZL,LOW(2*LcdInitTxt16)
.ENDIF
rcall LcdText
.IF cDisplay2
ldi rmp,0xC0 ; line 2
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
.ELSE
ldi XH,HIGH(sResult+25)
ldi XL,LOW(sResult+25)
ldi ZH,HIGH(2*LcdInitTxtMode)
ldi ZL,LOW(2*LcdInitTxtMode)
ldi rmp,6
LcdInitMode:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne LcdInitMode
ldi rmp,16
.ENDIF
rcall LcdText
.ENDIF
ret
.IF cDisplay8
LcdInitTxt8:
.DB "F-CNT V1"
.IF cDisplay2
.DB "-DG4FAC-"
.ENDIF
.ELSE
LcdInitTxt16:
.DB "Freq-counter V01"
.IF cDisplay2
.DB " (C)2005 DG4FAC "
LcdInitTxtMode:
.DB " Mode="
.ENDIF
.ENDIF
;
; Display frequency/time on Lcd
;
LcdDisplayFT:
.IF ! cDisplay2 ; single line display
cpi rMode,cModeVoltage ; voltage display selected?
breq LcdDisplayFT2
.ENDIF
ldi rmp,$80 ; set display position to line 1
rcall LcdRs4
rcall Delay40us
ldi ZH,HIGH(sResult) ; point Z to line buffer
ldi ZL,LOW(sResult)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayFT1:
ld R0,Z+ ; read a char
rcall LcdData4 ; display on LCD
dec rmp
brne LcdDisplayFT1
LcdDisplayFT2:
ret
;
; Display voltage on the display
;
LcdDisplayU:
.IF cDisplay2 ; two-line LCD connected
.IF !cDisplay8
lds rmp,sModeNext
subi rmp,-'0'
sts sResult+31,rmp
.ENDIF
ldi rmp,$C0 ; output to line 2
.ELSE
cpi rMode,cModeVoltage ; check switch
brne LcdDisplayU2
ldi rmp,$80 ; output to line 1
.ENDIF
rcall LcdRs4 ; set output position
rcall Delay40us
ldi ZH,HIGH(sResult+16) ; point to result
ldi ZL,LOW(sResult+16)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayU1:
ld R0,Z+ ; read character
rcall LcdData4
dec rmp ; next char
brne LcdDisplayU1 ; continue with chars
LcdDisplayU2:
ret
;
.ENDIF ; end LCD routines to be included
;
; ===========================================
; Uart routines
; ===========================================
;
.IF cUart
UartInit: ; Init the Uart on startup
.EQU cUbrr = (cFreq/cBaud/16)-1 ; calculating UBRR single speed
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi rmp,HIGH(cUbrr) ; set URSEL to zero, set baudrate msb
out UBRRH,rmp
ldi rmp,LOW(cUbrr) ; set baudrate lsb
out UBRRL,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; set 8 bit characters
out UCSRC,rmp
ldi rmp,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable RX/TX and RX-Ints
out UCSRB,rmp
rcall delay10ms ; delay for 10 ms duration
ldi ZH,HIGH(2*txtUartInit)
ldi ZL,LOW(2*txtUartInit)
rjmp UartSendTxt
;
UartRxLine:
cbr rFlg,1<<bUartRxLine ; clear line complete flag
ldi ZH,HIGH(2*txtUartCursor)
ldi ZL,LOW(2*txtUartCursor)
rjmp UartSendTxt
;
; Send character in rmp over Uart
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartSendChar
out UDR,rmp
ret
;
; Monitoring the voltage over the Uart
;
UartMonU:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonU ; displays voltage over Uart
ret
lds rmp,sUartMonUCnt ; read counter
dec rmp
sts sUartMonUCnt,rmp
brne UartMonU2
lds rmp,sUartMonURpt
sts sUartMonUCnt,rmp
ldi ZH,HIGH(sResult+16)
ldi ZL,LOW(sResult+16)
ldi rmp,8
UartMonU1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonU1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonU1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonU2:
ret
;
; Send text from flash to UART, null byte ends transmit
;
UartSendTxt:
lpm ; read character from flash
adiw ZL,1
tst R0 ; check end of text
breq UartSendTxtRet
UartSendTxtWait:
sbis UCSRA,UDRE ; wait for empty char
rjmp UartSendTxtWait
out UDR,R0 ; send char
rjmp UartSendTxt
UartSendTxtRet:
ret
;
; Uart text constants
;
txtUartInit:
.DB " ",cClrScr
.DB "************************************************* ",cCr,cLf
.DB "* Frequency- and voltmeter (C)2005 by g.schmidt * ",cCr,cLf
.DB "************************************************* ",cCr,cLf
txtUartMenue:
.DB cCr,cLf,"Commands: <h>elp",cCr,cLf
txtUartCursor:
.DB cCr,cLf,"i> ",cNul
.ENDIF
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_de/fcount/fcountV02.asm (3 of 3)1/20/2009 7:51:44 PM


http://www.avr-asm-tutorial.net/avr_gra/exp2313.gif

http://www.avr-asm-tutorial.net/avr_gra/exp2313.gif1/20/2009 7:51:47 PM
Sitemap of http://www.avr-asm-tutorial.net

Sitemap of http://www.avr-asm-tutorial.net,
english part
● English mainpage
● Beginner's introduction to AVR assembler language
❍ Beginner's intro in one pdf-file: beginner_en.pdf

❍ Hardware for programming

❍ Why programming in assembler?

❍ Tools for AVR assembly programming

■ First steps with Studio 4

■ Studio 3.5.2 Introduction

■ Directives in assembler

■ Structure of AVR-assembler-programs

■ Standard 8515 programming file structure

❍ Using registers in assembler

❍ Using ports in assembler

■ Port details of an AT90S8515

❍ Using SRAM in assembler

❍ Relative and absolute jumps, Reset- and Interrupt-vectors

❍ Calculations in assembler

❍ Tables: functional and alphabetic order, ports, vectors, abbreviations, directives,

expressions
● Binary calculations in AVR Assembler
❍ Binary multiplication in AVR Assembler

❍ Multiplication of two 8-bit-binaries

❍ Binary division in AVR Assembler

❍ Division of a 16-bit-binary by a 8-bit-binary

❍ Number format conversion AVR-Assembler

❍ 8-bit binary conversion to 3-digit fixed decimal in AVR Assembler

❍ 10-bit binary to 4-digit fixed decimal conversion in AVR Assembler

❍ Source code of number format conversion routines

❍ Conversion to fixed decimal numbers in AVR assembler

❍ Hardware multiplication with ATmega

● Four beginner's examples


❍ Test 1: Learn to know parts of the board hardware output to the LEDs

❍ Test 2: Learn to more about the board: Input from a port

❍ Test 3: Reading the timer in polling mode

❍ Test 4: Timer in Interrupt mode

● Using the AVR-Hardware of an AT90S8515 on a STK200


❍ Requirements for the use of the examples

❍ Demonstrates the use of the EEPROM

❍ Access to external SRAM of an AT90S8515

❍ Demonstration of a memory-mapped LCD on the STK200 AVR board

■ Test routines for the LCD

■ Clock routine for the ATMEL STK200 board with an LCD connected

❍ Tests the Serial Communication Port

■ Connecting to a serial PC interface

■ Sending hex echoes over the serial interface

❍ Connecting a 16-switch keypad to a port

● AVR-Applications of an AT90S8515 on the STK200


❍ XTal Clock on a AT90S2313, DCF synchronized

■ Schematic clock.pdf

❍ Decoder for remote control signals

■ Time flow pcm2flow.pdf

■ Schaltbild pcm2pwg4.pdf

■ Decoder sotware for remote control signals

❍ Terminal controled signal generator

● Digital signal generator


❍ Source code main, html

❍ Source code LCD, html

❍ Source code frequency table, html

❍ Source code, asm

❍ Schematic

● Frequency counter, 9 modes, 16 MHz xtal


❍ Source code, html

❍ Source code, asm

❍ Scheme, processor unit, gif

❍ Preamp/Prescaler, gif

● Eggtimer with ATtiny2313V


❍ Schematic, big GIF

❍ Schematic, small GIF

❍ Source code, html

❍ Source code, asm

● Stepper controller/driver with ATtiny13


❍ Source code, html

❍ Source code, asm

❍ Schematic, controller, PDF

❍ Schematic, controller, small gif

❍ Board picture, jpg

❍ Schematic, power supply, PDF

❍ Schematic, power supply, small gif

❍ Picture, power supply, jpg

❍ Picture, steppermotor, jpg

❍ Picture, controller and motor, small jpg

● Connecting a 2-line-LCD to a STK500 port

● LCD base rountines for a 4-bit connection


● Software clock connecting a LCD display to a STK500 port

● AVR-PWM-ADC-Test for STK500

● Software for an PWM-ADC

● R/2R-network as DAC for an AVR


● Some special know-how

● Using the LPM instruction


● Jumping via the stack
● Testprogram to demonstrate Macros, Example 1
● Testprogram to demonstrate Macros, Example 2
● Testprogram to demonstrate Macros, Example 3

● ANSI-terminal programmable signal generator


● Connecting a keypad to an AVR

● Resistor-encoder, Open Office Spreadsheet


● Resistor-encoder, Excel Spreadsheat

● Gerd's AVR Assembler

● English download page


● ReadMe.Txt
● gavrasm_lin_en_22.zip
● DosRead.Txt
● gavrasm_sources_doswin_22.zip
● gavrasm_dos_en_22.zip
● gavrasm_sources_lin_22.zip
● gavrasm_win_en_22.zip
● All instructions: instr.asm
● All instructions (DOS/Win format): instr_doswin.asm
● All instructions (Linux format): instr_linux.asm
● Introduction to Gerd's AVR Assembler

● Gerd's AVR Assembler Caller

● ReadMe.txt
● Software (Win): gavrasmW.zip

● Akkuload - a microprocessor controlled loader for accu cells

● Akkuload - a microprocessor controlled loader for accu cells


❍ All packed: akkuload.zip

❍ Main source: akkuload.asm

❍ akkuuart.asm

❍ akkucalc.asm

❍ akkukey.asm

❍ akkulcd.asm

● Schematic, processor, GIF-format


● Schematic, Analog part, GIF-format
● Schematic, Analog part, PDF-format

● Links to all source files of this tutorial

● 8515std.asm
● ADC8.asm
● avr_pwm1.pas
● CONVERT.asm
● CLOCK.asm
● DIV8E.asm
● eggtimer.asm
● FP_CONV10_EN.asm
● FP_CONV8_EN.asm
● Lcd4IncCE.asm
● Lcd4IncE.asm
● LCD_INC.asm
● LCD_TEST.asm
● MULT8E.asm
● MUSIC.asm
● PCM2PWG4.asm
● PWGSIO2.asm
● r2r.pas
● SAWTOOTH1.asm
● SAWTOOTH2.asm
● sine8_25.txt
● SINEWAVE.asm
● sinewave.pas
● SIOHEX.asm
● TEST1.asm
● TEST2.asm
● TEST3.asm
● TEST4.asm
● TESTEEP.asm
● TESTJMP.asm
● TESTKBD.asm
● TESTLCD.asm
● TESTMAC1.asm
● TESTMAC2.asm
● TESTMAC3.asm
● TESTRAM.asm
● TESTSIO.asm
● TESTLPM.asm
● TRIANGLE.asm

http://www.avr-asm-tutorial.net/sitemap_en.html (1 of 2)1/20/2009 7:51:59 PM


Sitemap of http://www.avr-asm-tutorial.net

©2002..2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/sitemap_en.html (2 of 2)1/20/2009 7:51:59 PM


Beginner's introduction to AVR assembler language

Path: Home => AVR overview => beginners intro => menue

Beginners Programming in AVR


Main Assembler
Hardware
ISP The following pages are written for all people that try to program in assembler
ParPortProg language for the first time and like to start with programming ATMEL-AVRs
Exp2313 AT90Sxxxx. Some basic programming techniques are shown that are
Boards necessary. During later learning stages these informations are useful and so try
Why Asm? to learn this first. Tables are included for easier programming.
Tools There might be some bugs in these pages. Bug reports and hints for improving
Edit these pages are very welcome.
Asm
ISP Overview on the beginners programming
Studio3
tutorial
Studio4
Structure
Register Theme What is that Commands
What? ISP-Interface, Parallel-Port-
Which? Programmer, Experimental
Pointer Hardware -
2313 board, Commercial
Tables
boards
Select
Ports Why learn assembler
Why -
What? language?
Which? Editor, Assembler, ISP,
Status Tools -
Studio3, Studio4, Structure
SRAM
What? What is a Register? .DEF, LDI, MOV
Why? Which different registers are CLR, ANDI, CBR, CPI,
How? available SBCI, SBR, SER, SUBI
Stack
Register LD, ST, LPM, ADIW, SBIW, .
Run Register as Pointer
Reset
DB, .DW
Branch What can be packed into a
Timing
-
register?
Macros
.INCLUDE, OUT, IN, CBI,
Subrout What is a Port?
SBI, SLEEP
Interrupts
Calc Ports Which Ports are available? -
Numbers Status register as most
Bits CLx, SEx, BCLR, BSET
relevant port
Shift
Add, Sub What is SRAM? -
convert For which purposes SRAM is
Tables -
SRAM used
Commands
functional How to use SRAM? STS, LDS, LD, ST, STD, LDD
alphabetic Stack in SRAM PUSH, POP, RCALL, RET
Ports
What happens during a Reset? -
functional
alphabetic .CSEG, .DSEG, .ORG, .
Linear program runs and
Vectors ESEG, INC, BRNE, BREQ,
branches
Abbreviations BRxx
Directives
Advanced Program run Timing of commands NOP, DEC
Expressions Macros .MACRO, .ENDMACRO
Shift Left RET, RCALL, RJMP, SBRC,
Subroutines
AVR-page SBRS, SBIC, SBIS
Home Interrupts RETI
Numbers and characters -
ORI, OR, ANDI, AND, CBR,
Bit manipulation SBR, EOR, COM, NEG,
BLD, CLT, SET, BST
Calculations LSL, LSR, ASR, ROL, ROR,
Shift and rotate
SWAP
Adding, Subtracting, ADD, ADC, SUB, SBC, CP,
Compares CPC, CPI, TST
Format changes .DB, .DW
Commands by function -
Commands alphabetic -
Ports -
Tables Vectors -
Abbreviations -
Directives all dot directives
Expressions -

To the top of this page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/index.html1/20/2009 7:52:05 PM
Beginners programming in AVR Assembler

Path: Home => AVR overview => beginners intro => menue

Beginners Programming in AVR Assembler


The following pages are written for all people that try to program in assembler language for the first
time and like to start with programming ATMEL-AVRs AT90Sxxxx. Some basic programming
techniques are shown that are necessary. During later learning stages these informations are useful
and so try to learn this first. Tables are included for easier programming.
There might be some bugs in these pages. Bug reports and hints for improving these pages are very
welcome.

Overview on the beginners programming tutorial

Theme What is that Commands


ISP-Interface, Parallel-Port-Programmer,
Hardware Experimental 2313 board, Commercial -
boards
Why Why learn assembler language? -
Editor, Assembler, ISP, Studio3, Studio4,
Tools -
Structure
What is a Register? .DEF, LDI, MOV
CLR, ANDI, CBR, CPI, SBCI, SBR,
Which different registers are available
Register SER, SUBI
Register as Pointer LD, ST, LPM, ADIW, SBIW, .DB, .DW
What can be packed into a register? -
What is a Port? .INCLUDE, OUT, IN, CBI, SBI, SLEEP
Ports Which Ports are available? -
Status register as most relevant port CLx, SEx, BCLR, BSET
What is SRAM? -
For which purposes SRAM is used -
SRAM
How to use SRAM? STS, LDS, LD, ST, STD, LDD
Stack in SRAM PUSH, POP, RCALL, RET
What happens during a Reset? -
.CSEG, .DSEG, .ORG, .ESEG, INC,
Linear program runs and branches
BRNE, BREQ, BRxx
Timing of commands NOP, DEC
Program run
Macros .MACRO, .ENDMACRO
RET, RCALL, RJMP, SBRC, SBRS,
Subroutines
SBIC, SBIS
Interrupts RETI
Numbers and characters -
ORI, OR, ANDI, AND, CBR, SBR, EOR,
Bit manipulation
COM, NEG, BLD, CLT, SET, BST
Calculations Shift and rotate LSL, LSR, ASR, ROL, ROR, SWAP
ADD, ADC, SUB, SBC, CP, CPC, CPI,
Adding, Subtracting, Compares
TST
Format changes .DB, .DW
Commands by function -
Commands alphabetic -
Ports -
Tables Vectors -
Abbreviations -
Directives all dot directives
Expressions -

To the top of this page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/RIGHT.html1/20/2009 7:52:08 PM
Commands in AVR-assembler language

Path: Home => AVR-overview => programming => tables

Programming in AVR assembler language


Tables
● Commands sorted by function
● Commands sorted by alphabet
● Ports
● Abbreviations

Commands sorted by function


For the abbreviations used see the list of abbreviations.
Function Subfunction Command Flags Clk
0 CLR r1 ZNV 1
Register
255 SER rh 1
set
Constant LDI rh,c255 1
Register => Register MOV r1,r2 1
SRAM => Register, direct LDS r1,c65535 2
SRAM => Register LD r1,rp 2
SRAM => Register and INC LD r1,rp+ 2
DEC, SRAM => Register LD r1,-rp 2
SRAM, displaced => Register LDD r1,ry+k63 2
Port => Register IN r1,p1 1
Stack => Register POP r1 2
Copy
Program storage Z => R0 LPM 3
Register => SRAM, direct STS c65535,r1 2
Register => SRAM ST rp,r1 2
Register => SRAM and INC ST rp+,r1 2
DEC, Register => SRAM ST -rp,r1 2
Register => SRAM, displaced STD ry+k63,r1 2
Register => Port OUT p1,r1 1
Register => Stack PUSH r1 2
8 Bit, +1 INC r1 ZNV 1
8 Bit ADD r1,r2 ZCNVH 1
Add
8 Bit + Carry ADC r1,r2 ZCNVH 1
16 Bit, constant ADIW rd,k63 ZCNVS 2
8 Bit, -1 DEC r1 ZNV 1
8 Bit SUB r1,r2 ZCNVH 1
8 Bit, constant SUBI rh,c255 ZCNVH 1
Subtract
8 Bit - Carry SBC r1,r2 ZCNVH 1
8 Bit - Carry, constant SBCI rh,c255 ZCNVH 1
16 Bit SBIW rd,k63 ZCNVS 2
logic, left LSL r1 ZCNV 1
logic, right LSR r1 ZCNV 1
Rotate, left over Carry ROL r1 ZCNV 1
Shift
Rotate, right over Carry ROR r1 ZCNV 1
Arithmetic, right ASR r1 ZCNV 1
Nibble exchange SWAP r1 1
And AND r1,r2 ZNV 1
And, constant ANDI rh,c255 Z N V 1
Or OR r1,r2 ZNV 1
Binary Or, constant ORI rh,c255 ZNV 1
Exclusive-Or EOR r1,r2 ZNV 1
Ones-complement COM r1 ZCNV 1
Twos-complement NEG r1 ZCNVH 1
Register, set SBR rh,c255 ZNV 1
Register, clear CBR rh,255 ZNV 1

Bits Register, copy to T-Flag BST r1,b7 T 1


change Register, copy from T-Flag BLD r1,b7 1
Port, set SBI pl,b7 2
Port, clear CBI pl,b7 2
Zero-Flag SEZ Z 1
Carry Flag SEC C 1
Negative Flag SEN N 1

Statusbit Twos complement carry Flag SEV V 1


set Half carry Flag SEH H 1
Signed Flag SES S 1
Transfer Flag SET T 1
Interrupt Enable Flag SEI I 1
Zero-Flag CLZ Z 1
Carry Flag CLC C 1
Negative Flag CLN N 1

Statusbit Twos complement carry Flag CLV V 1


clear Half carry Flag CLH H 1
Signed Flag CLS S 1
Transfer Flag CLT T 1
Interrupt Enable Flag CLI I 1
Register, Register CP r1,r2 ZCNVH 1
Register, Register + Carry CPC r1,r2 ZCNVH 1
Compare
Register, constant CPI rh,c255 ZCNVH 1
Register, ≤0 TST r1 ZNV 1
Relative RJMP c4096 2
Indirect, Address in Z IJMP 2

Immediate Subroutine, relative RCALL c4096 3


Jump Subroutine, Address in Z ICALL 3
Return from Subroutine RET 4
Return from Interrupt RETI I 4
Statusbit set BRBS b7,c127 1/2
Statusbit clear BRBC b7,c127 1/2
Jump if equal BREQ c127 1/2
Jump if equal BRNE c127 1/2
Jump if carry BRCS c127 1/2
Jump if carry clear BRCC c127 1/2
Jump if equal or greater BRSH c127 1/2
Jump if lower BRLO c127 1/2
Jump if negative BRMI c127 1/2

Conditioned Jump if positive BRPL c127 1/2


Jump Jump if greater or equal (Signed) BRGE c127 1/2
Jump if lower than zero (Signed) BRLT c127 1/2
Jump on half carry set BRHS c127 1/2
Jump if half carry clear BRHC c127 1/2
Jump if T-Flag set BRTS c127 1/2
Jump if T-Flag clear BRTC c127 1/2
Jump if Twos complement carry set BRVS c127 1/2
Jump if Twos complement carry clear BRVC c127 1/2
Jump if Interrupts enabled BRIE c127 1/2
Jump if Interrupts disabled BRID c127 1/2
Registerbit=0 SBRC r1,b7 1/2/3
Registerbit=1 SBRS r1,b7 1/2/3
Conditioned
Portbit=0 SBIC pl,b7 1/2/3
Jumps
Portbit=1 SBIS pl,b7 1/2/3
Compare, jump if equal CPSE r1,r2 1/2/3
No Operation NOP 1
Others Sleep SLEEP 1
Watchdog Reset WDR 1

To the top of that page

Command list in alphabetic order

Assembler directives

.CSEG
.DB
.DEF
.DW
.ENDMACRO
.ESEG
.EQU
.INCLUDE
.MACRO
.ORG

Commands

ADC r1,r2
ADD r1,r2
ADIW rd,k63
AND r1,r2
ANDI rh,c255, Register
ASR r1
BLD r1,b7
BRCC c127
BRCS c127
BREQ c127
BRGE c127
BRHC c127
BRHS c127
BRID c127
BRIE c127
BRLO c127
BRLT c127
BRMI c127
BRNE c127
BRPL c127
BRSH c127
BRTC c127
BRTS c127
BRVC c127
BRVS c127
BST r1,b7
CBI pl,b7
CBR rh,255, Register
CLC
CLH
CLI
CLN
CLR r1
CLS
CLT, (command example)
CLV
CLZ
COM r1
CP r1,r2
CPC r1,r2
CPI rh,c255, Register
CPSE r1,r2
DEC r1
EOR r1,r2
ICALL
IJMP IN r1,p1
INC r1
LD rp,(rp,rp+,-rp) (Register), (SRAM access), Ports
LDD r1,ry+k63
LDI rh,c255 (Register), Pointer
LDS r1,c65535
LPM
LSL r1
LSR r1
MOV r1,r2
NEG r1
NOP
OR r1,r2 ORI rh,c255 OUT p1,r1
POP r1, (in Int-routine)
PUSH r1, (in Int-routine)
RCALL c4096
RET, (in Int-routine)
RETI
RJMP c4096
ROL r1
ROR r1
SBC r1,r2
SBCI rh,c255
SBI pl,b7
SBIC pl,b7
SBIS pl,b7
SBIW rd,k63
SBR rh,255, Register
SBRC r1,b7
SBRS r1,b7
SEC
SEH
SEI, (in Int-routine)
SEN
SER rh
SES
SET, (example)
SEV
SEZ
SLEEP
ST (rp/rp+/-rp),r1 (Register), SRAM access, Ports
STD ry+k63,r1
STS c65535,r1
SUB r1,r2
SUBI rh,c255
SWAP r1
TST r1
WDR

To the top of that page

Ports, alphabetic order


ACSR, Analog Comparator Control and Status Register
DDRx, Port x Data Direction Register
EEAR, EEPROM Adress Register
EECR, EEPROM Control Register
EEDR, EEPROM Data Register
GIFR, General Interrupt Flag Register
GIMSK, General Interrupt Mask Register
ICR1L/H, Input Capture Register 1
MCUCR, MCU General Control Register
OCR1A, Output Compare Register 1 A
OCR1B, Output Compare Register 1 B
PINx, Port Input Access
PORTx, Port x Output Register
SPL/SPH, Stackpointer
SPCR, Serial Peripheral Control Register
SPDR, Serial Peripheral Data Register
SPSR, Serial Peripheral Status Register
SREG, Status Register
TCCR0, Timer/Counter Control Register, Timer 0
TCCR1A, Timer/Counter Control Register 1 A
TCCR1B, Timer/Counter Control Register 1 B
TCNT0, Timer/Counter Register, Counter 0
TCNT1, Timer/Counter Register, Counter 1
TIFR, Timer Interrupt Flag Register
TIMSK, Timer Interrupt Mask Register
UBRR, UART Baud Rate Register
UCR, UART Control Register
UDR, UART Data Register
WDTCR, Watchdog Timer Control Register

To the top of that page

List of abbreviations
The abbreviations used are chosen to include the value range. Register pairs are named by the lower
of the two registers. Constants in jump commands are automatically calculated from the respective
labels during assembly.
Category Abbrev. Means ... Value range
r1 Ordinary Source and Target register
R0..R31
r2 Ordinary Source register
rh Upper page register R16..R31
Register R24(R25), R26(R27), R28(R29), R30
rd Twin register
(R31)
rp Pointer register X=R26(R27), Y=R28(R29), Z=R30(R31)
ry Pointer register with displacement Y=R28(R29), Z=R30(R31)
k63 Pointer-constant 0..63
c127 Conditioned jump distance -64..+63
Constant c255 8-Bit-Constant 0..255
c4096 Relative jump distance -2048..+2047
c65535 16-Bit-Address 0..65535
Bit b7 Bit position 0..7
p1 Ordinary Port 0..63
Port
pl Lower page port 0..31

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/COMMANDS.html1/20/2009 7:52:12 PM
Register in the AVR

Path: Home => AVR-overview => Assembler intro => Registers

Introduction to AVR assembler programming


for beginners
What is a register?
Registers are special storages with 8 bits capacity and they look like this:
7 6 5 4 3 2 1 0

Note the numeration of these bits: the least significant bit starts with zero (20 = 1).
A register can either store numbers from 0 to 255 (positive number, no negative values), or numbers
from -128 to +127 (whole number with a sign bit in bit 7), or a value representing an ASCII-coded
character (e.g. 'A'), or just eight single bits that do not have something to do with each other (e.g. for
eight single flags used to signal eight different yes/no decisions).
The special character of registers, compared to other storage sites, is that

● they can be used directly in assembler commands,


● operations with their content require only a single command word,
● they are connected directly to the central processing unit called the accumulator,
● they are source and target for calculations.

There are 32 registers in an AVR. They are originally named R0 to R31, but you can choose to name
them to more meaningful names using an assembler directive. An example:

.DEF MyPreferredRegister = R16

Note that assembler directives like this are only meaningful for the assembler but do not produce any
code that is executable in the AVR target chip. Instead of using the register name R16 we can now
use our own name MyPreferredRegister, if we want to use R16 within a command. So we write a
little bit more text each time we use this register, but we have an association what might be the
content of this register.

Using the command line

LDI MyPreferredRegister, 150

which means: load the number 150 immediately to the register R16, LoaD Immediate. This loads a
fixed value or a constant to that register. Following the assembly or translation of this code the
program storage written to the AVR chip looks like this:

000000 E906

The load command code as well as the target register (R16) as well as the value of the constant (150)
is part of the hex value E906, even if you don't see this directly. Don't be afraid: you don't have to
remember this coding because the assembler knows how to translate all this to yield E906.

Within one command two different registers can play a role. The easiest command of this type is the
copy command MOV. It copies the content of one register to another register. Like this:

.DEF MyPreferredRegister = R16


.DEF AnotherRegister = R15
LDI MyPreferredRegister, 150
MOV AnotherRegister, MyPreferredRegister

The first two lines of this monster program are directives that define the new names of the registers
R16 and R15 for the assembler. Again, these lines do not produce any code for the AVR. The
command lines with LDI and MOV produce code:

000000 E906
000001 2F01

The commands write 150 into register R16 and copy its content to the target register R15.
IMPORTANT NOTE:

The first register is always the target register where the result is written to!

(This is unfortunately different from what one expects or from how we speak. It is a simple
convention that was once defined that way to confuse the beginners learning assembler. That is why
assembler is that complicated.)

To the top of that page

Different registers
The beginner might want to write the above commands like this:

.DEF AnotherRegister = R15


LDI AnotherRegister, 150

And: you lost. Only the registers from R16 to R31 load a constant immediately with the LDI
command, R0 to R15 don't do that. This restriction is not very fine, but could not be avoided during
construction of the command set for the AVRs.

There is one exception from that rule: setting a register to Zero. This command

CLR MyPreferredRegister

is valid for all registers.

Besides the LDI command you will find this register class restriction with the following additional
commands:

● ANDI Rx,K ; Bit-And of register Rx with a constant value K,


● CBR Rx,M ; Clear all bits in register Rx that are set to one within the constant mask value M,
● CPI Rx,K ; Compare the content of the register Rx with a constant value K,
● SBCI Rx,K ; Subtract the constant K and the current value of the carry flag from the content
of register Rx and store the result in register Rx,
● SBR Rx,M ; Set all bits in register Rx to one, that are one in the constant mask M,
● SER Rx ; Set all bits in register Rx to one (equal to LDI Rx,255),
● SUBI Rx,K ; Subtract the constant K from the content of register Rx and store the result in
register Rx.

In all these commands the register must be between R16 and R31! If you plan to use these commands
you should select one of these registers for that operation. It is easier to program. This is an additional
reason why you should use the directive to define a register's name, because you can easier change
the registers location afterwards.

To the top of that page

Pointer-register
A very special extra role is defined for the register pairs R26:R27, R28:R29 and R30:R31. The role is
so important that these pairs have extra names in assembler: X, Y and Z. These pairs are 16-bit
pointer registers, able to point to adresses with max. 16-bit into SRAM locations (X, Y or Z) or into
locations in program memory (Z).

The lower byte of the 16-bit-adress is located in the lower register, the higher byte in the upper
register. Both parts have their own names, e.g. the higher byte of Z is named ZH (=R31), the lower
Byte is ZL (=R30). These names are defined in the standard header file for the chips. Dividing these
16-bit-pointer-names into two different bytes is done like follows:

.EQU Adress = RAMEND ; RAMEND is the highest 16-bit adress in SRAM


LDI YH,HIGH(Adress) ; Set the MSB
LDI YL,LOW(Adress) ; Set the LSB

Accesses via pointers are programmed with specially designed commands. Read access is named LD
(LoaD), write access named ST (STore), e.g. with the X-pointer:
Pointer Sequence Example
LD R1,X
X Read/Write from adress X, don't change the pointer
ST X,R1
LD R1,X+
X+ Read/Write from/to adress X and increment the pointer afterwards by one
ST X+,R1
LD R1,-X
-X Decrement the pointer by one and read/write from/to the new adress afterwards
ST -X,R1
Similiarly you can use Y and Z for that purpose.

There is only one command for the read access to the program storage. It is defined for the pointer
pair Z and it is named LPM (Load from Program Memory). The command copies the byte at adress Z
in the program memory to the register R0. As the program memory is organised word-wise (one
command on one adress consists of 16 bits or two bytes or one word) the least significant bit selects
the lower or higher byte (0=lower byte, 1= higher byte). Because of this the original adress must be
multiplied by 2 and access is limited to 15-bit or 32 kB program memory. Like this:

LDI ZH,HIGH(2*Adress)
LDI ZL,LOW(2*Adress)
LPM

Following this command the adress must be incremented to point to the next byte in program
memory. As this is used very often a special pointer incrementation command has been defined to do
this:

ADIW ZL,1
LPM

ADIW means ADd Immediate Word and a maximum of 63 can be added this way. Note that the
assembler expects the lower of the pointer register pair ZL as first parameter. This is somewhat
confusing as addition is done as 16-bit- operation.
The complement command, subtracting a constant value of between 0 and 63 from a 16-bit pointer
register is named SBIW, Subtract Immediate Word. (SuBtract Immediate Word). ADIW and SBIW
are possible for the pointer register pairs X, Y and Z and for the register pair R25:R24, that does not
have an extra name and does not allow access to SRAM or program memory locations. R25:R24 is
ideal for handling 16-bit values.

How to insert that table of values in the program memory? This is done with the assembler directives .
DB and .DW. With that you can insert bytewise or wordwise lists of values. Bytewise organised lists
look like this:

.DB 123,45,67,89 ; a list of four bytes


.DB "This is a text. " ; a list of byte characters

You should always place an even number of bytes on each single line. Otherwise the assembler will
add a zero byte at the end, which might be unwanted.
The similiar list of words looks like this:

.DW 12345,6789 ; a list of two words

Instead of constants you can also place labels (jump targets) on that list, like that:

Label1:
[ ... here are some commands ... ]
Label2:
[ ... here are some more commands ... ]
Table:
.DW Label1,Label2 ; a wordwise list of labels

Note that reading the labels with LPM first yields the lower byte of the word.

A very special application for the pointer registers is the access to the registers themselves. The
registers are located in the first 32 bytes of the chip's adress space (at adress 0x0000 to 0x001F). This
access is only meaningful if you have to copy the register's content to SRAM or EEPROM or read
these values from there back into the registers.

More common for the use of pointers is the access to tables with fixed values in the program memory
space. Here is, as an example, a table with 10 different 16-bit values, where the fifth table value is
read to R25:R24:

MyTable:
.DW 0x1234,0x2345,0x3456,0x4568,0x5678 ; The table values, wordwise
.DW 0x6789,0x789A,0x89AB,0x9ABC,0xABCD ; organised
Read5: LDI ZH,HIGH(MyTable*2) ; Adress of table to pointer Z
LDI ZL,LOW(MyTable*2) ; multiplied by 2 for bytewise access
ADIW ZL,10 ; Point to fifth value in table
LPM ; Read least significant byte from program memory
MOV R24,R0 ; Copy LSB to 16-bit register
ADIW ZL,1 ; Point to MSB in program memory
LPM ; Read MSB of table value
MOV R25,R0 ; Copy MSB to 16-bit register

This is only an example. You can calculate the table adress in Z from some input value, leading to the
respective table values. Tables can be organised byte- or character-wise, too.

To the top of that page

Recommendation for the use of registers


1. Define names for registers with the .DEF directive, never use them with their direct name Rx.
2. If you need pointer access reserve R26 to R31 for that purpose.
3. 16-bit-counter are best located R25:R24.
4. If you need to read from the program memory, e.g. fixed tables, reserve Z (R31:R30) and R0
for that purpose.
5. If you plan to have access to single bits within certain registers (e.g. for testing flags), use R16
to R23 for that purpose.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/REGISTER.html1/20/2009 7:52:20 PM
SRAM in the AVR

Path: Home => AVR-overview => Assembler intro => SRAM use

Introduction to AVR assembler programming for


beginners
Using SRAM in AVR assembler language
All AT90S-AVR-type MCUs have static RAM (SRAM) on board. Only very simple assembler
programs can avoid using this memory space by putting all info into registers. If you run out of
registers you should be able to program the SRAM to utilize more space.

What is SRAM?

SRAM are memories that are not directly accessable to the central processing unit (Arithmetic and
Logical Unit ALU, sometimes called accumulator) like the registers are. If you access these memory
locations you usually use a register as interim storage. In the following example a value in SRAM will
be copied to the register R2 (1st command), a calculation with the value in R3 is made and the result is
written to R3 (command 2). After that this value is written back to the SRAM location (command 3, not
shown here).

So it is clear that operations with values stored in the SRAM are slower to perform than those using
registers alone. On the other hand: the smallest AVR type has 128 bytes of SRAM available, much
more than the 32 registers can hold.

The types from AT90S8515 upwards offer the additional opportunity to connect additional external
RAM, expanding the internal 512 bytes. From the assembler point- of-view, external SRAM is
accessed like internal SRAM. No extra commands must be used for that external SRAM.

To the top of that page

For what purposes can I use SRAM?

Besides simple storage of values SRAM offers additional opportunities for its use. Not only access with
fixed addresses is possible, but also the use of pointers, so that floating access to subsequent locations
can be programmed. This way you can build up ring buffers for interim storage of values or calculated
tables. This is not possible with registers, because they are too few and need fixed access.

Even more relative is the access using an offset to a fixed starting address in one of the pointer
registers. In that case a fixed address is stored in a pointer register, a constant value is added to this
address and read/write access is made to that address with an offset. With that kind of access tables are
better used.

The most relevant use for SRAM is the so-called stack. You can push values to that stack, be it the
content of a register, a return address prior to calling a subroutine, or the return address prior to an
hardware-triggered interrupt.

To the top of that page

How to use SRAM?

To copy a value to a memory location in SRAM you have to define the address. The SRAM addresses
you can use reach from 0x0060 (hex notation) to the end of the physical SRAM on the chip (in the
AT90S8515 the highest accessable internal SRAM location is 0x025F). With the command

STS 0x0060, R1

the content of register R1 is copied to the first SRAM location. With

LDS R1, 0x0060

the SRAM content at address 0x0060 is copied to the register. This is the direct access with an address
that has to be defined by the programmer.

Symbolic names can be used to avoid handling fixed addresses, that require a lot of work, if you later
want to change the structure of your data in the SRAM. These names are easier to handle than hex
numbers, so give that address a name like:

.EQU MyPreferredStorageCell = 0x0060


STS MyPreferredStorageCell, R1

Yes, it isn't shorter, but easier to remember. Use whatever name that you find to be convenient.

Another kind of access to SRAM is the use of pointers. You need two registers for that purpose, that
hold the 16-bit address of the location. As we learned in the Pointer-Register-Division pointer registers
are the pairs X (XH:XL, R27:R26), Y (YH:YL, R29:R28) and Z (ZH:ZL, R31:R30). They allow access
to the location they point to directly (e.g. with ST X, R1), after prior decrementing the address by one
(e.g. ST -X, R1) or with subsequent incrementation of the address (e.g. ST X+, R1). A complete access
to three cells in a row looks like this:

.EQU MyPreferredStorageCell = 0x0060


.DEF MyPreferredRegister = R1
.DEF AnotherRegister = R2
.DEF AndAnotherRegister = R3
LDI XH, HIGH(MyPreferredStorageCell)
LDI XL, LOW(MyPreferredStorageCell)
LD MyPreferredRegister, X+
LD AnotherRegister, X+
LD AndAnotherRegister, X

Easy to operate, those pointers. And as easy as in other languages than assembler, that claim to be
easier to learn.

The third construction is a little bit more exotic and only experienced programmers use this. Let's
assume we very often in our program need to access three SRAM locations. Let's futher assume that we
have a spare pointer register pair, so we can afford to use it exclusively for our purpose. If we would
use the ST/LD instructions we always have to change the pointer if we access another location. Not
very convenient.
To avoid this, and to confuse the beginner, the access with offset was invented. During that access the
register value isn't changed. The address is calculated by temporarly adding the fixed offset. In the
above example the access to location 0x0062 would look like this. First, the pointer register is set to our
central location 0x0060:

.EQU MyPreferredStorageCell = 0x0060


.DEF MyPreferredRegister = R1
LDI YH, HIGH(MyPreferredStorageCell)
LDI YL, LOW(MyPreferredStorageCell)

Somewhere later in the program I'd like to access cell 0x0062:

STD Y+2, MyPreferredRegister

Note that 2 is not really added to Y, just temporarly. To confuse you further, this can only be done with
the Y- and Z-register-pair, not with the X-pointer!

The corresponding instruction for reading from SRAM with an offset

LDD MyPreferredRegister, Y+2

is also possible.

That's it with the SRAM, but wait: the most relevant use as stack is still to be learned.

To the top of that page

Use of SRAM as stack

The most common use of SRAM is its use as stack. The stack is a tower of wooden blocks. Each
additional block goes onto the top of the tower, each recall of a value removes the upmost block from
the tower. This structure is called Last-In-First-Out (LIFO) or easier: the last to go on top will be the
first coming down.

Defining SRAM as stack

To use SRAM as stack requires the setting of the stack pointer first. The stack pointer is a 16-bit-
pointer, accessable like a port. The double register is named SPH:SPL. SPH holds the most significant
address byte, SPL the least significant. This is only true, if the AVR type has more than 256 byte
SRAM. If not, SPH is undefined and must not and cannot be used. We assume we have more than 256
bytes in the following examples.

To construct the stack the stack pointer is loaded with the highest available SRAM address. (In our case
the tower grows downwards, towards lower addresses!).

.DEF MyPreferredRegister = R16


LDI MyPreferredRegister, HIGH(RAMEND) ; Upper byte
OUT SPH,MyPreferredRegister ; to stack pointer
LDI MyPreferredRegister, LOW(RAMEND) ; Lower byte
OUT SPL,MyPreferredRegister ; to stack pointer

The value RAMEND is, of course, specific for the processor type. It is defined in the INCLUDE file for
the processor type. The file 8515def.inc has the line:

.equ RAMEND =$25F ; Last On-Chip SRAM Location

The file 8515def.inc is included with the assembler directive

.INCLUDE "C:\somewhere\8515def.inc"

at the beginning of our assembler source code.

So we defined the stack now, and we don't have to care about the stack pointer any more, because
manipulations of that pointer are automatic.

Use of the stack

Using the stack is easy. The content of registers are pushed onto the stack like this:

PUSH MyPreferredRegister ; Throw that value

Where that value goes to is totally uninteresting. That the stack pointer was decremented after that
push, we don't have to care. If we need the content again, we just add the following instruction:

POP MyPreferredRegister ; Read back the value

With POP we just get the value that was last pushed on top of the stack. Pushing and popping registers
makes sense, if

● the content is again needed some lines of code later,


● all registers are in use, and if
● no other opportunity exists to store that value somewhere else.

If these conditions are not given, the use of the stack for saving registers is useless and just wastes
processor time.

More sense makes the use of the stack in subroutines, where you have to return to the program location
that called the routine. In that case the calling program code pushes the return address (the current
program counter value) onto the stack and jumps to the subroutine. After its execution the subroutine
pops the return address from the stack and loads it back into the program counter. Program execution is
continued exactly one instruction behind the call instruction:

RCALL Somewhat ; Jump to the label somewhat


[...] here we continue with the program.

Here the jump to the label somewhat somewhere in the program code,

Somewhat: ; this is the jump address


[...] Here we do something
[...] and we are finished and want to jump back to the calling location:
RET

During execution of the RCALL instruction the already incremented program counter, a 16-bit-address,
is pushed onto the stack, using two pushes. By reaching the RET instruction the content of the previous
program counter is reloaded with two pops and execution continues there.
You don't need to care about the address of the stack, where the counter is loaded to. This address is
automatically generated. Even if you call a subroutine within that subroutine the stack function is fine.
This just packs two return addresses on top of the stack, the nested subroutine removes the first one, the
calling subroutine the remaining one. As long as there is enough SRAM everything is fine.

Servicing hardware interrupts isn't possible without the stack. Interrupts stop the normal exection of the
program, wherever the program currently is. After execution of a specific service routine as a reaction
to that interrupt program execution must return to the previous location, before the interrupt occurred.
This would not be possible if the stack is not able to store the return address.

Bugs with the stack operation

For the beginner there are a lot of possible bugs, if you first learn to use stack.
Very clever is the use of the stack without first setting the stack pointer. Because this pointer is set to
zero at program start the pointer points to register R0. Pushing a byte results in a write to that register,
overwriting its previous content. An additional push to the stack writes to 0xFFFF, an undefined
position (if you don't have external SRAM there). A RCALL and RET will return to a strange address
in program memory. Be sure: there is no warning, like a window popping up saying something like
Illegal Access to Mem location xxxx.
Another opportunity to construct bugs is to forget to pop a previously pushed value, or popping a value
without pushing one first.
In a very few cases the stack overflows to below the first SRAM location. This happens in case of a
never-ending recursive call. After reaching the lowest SRAM location the next pushes write to the ports
(0x005F to 0x0020), then to the registers (0x001F to 0x0000). Funny and unpredictable things happen
with the chip hardware, if this goes on. Avoid this bug, it can destroy your hardware!

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/SRAM.html1/20/2009 7:52:26 PM
Ports in the AVR

Path: Home => AVR-overview => Assembler intro => Ports

Introduction to AVR assembler programming


for beginners
What is a Port?
Ports in the AVR are gates from the central processing unit to internal and external hard- and
software components. The CPU communicates with these components, reads from them or writes to
them, e.g. to the timers or the parallel ports. The most used port is the flag register, where results of
previous operations are written to and branch conditions are read from.

There are 64 different ports, which are not physically available in all different AVR types. Depending
on the storage space and other internal hardware the different ports are either available and accessable
or not. Which of these ports can be used is listed in the data sheets for the processor type.

Ports have a fixed address, over which the CPU communicates. The address is independent from the
type of AVR. So e.g. the port adress of port B is always 0x18 (0x stands for hexadecimal notation).
You don't have to remember these port adresses, they have convenient aliases. These names are
defined in the include files (header files) for the different AVR types, that are provided from the
producer. The include files have a line defining port B's address as follows:

.EQU PORTB, 0x18

So we just have to remember the name of port B, not its location in the I/O space of the chip. The
include file 8515def.inc is involved by the assembler directive

.INCLUDE "C:\Somewhere\8515def.inc"

and the registers of the 8515 are all defined then and easily accessable.

Ports usually are organised as 8-bit numbers, but can also hold up to 8 single bits that don't have
much to do with each other. If these single bits have a meaning they have their own name associated
in the include file, e.g. to enable manipulation of a single bit. Due to that name convention you don't
have to remember these bit positions. These names are defined in the data sheets and are given in the
include file, too. They are provided here in the port tables.

As an example the MCU General Control Register, called MCUCR, consists of a number of single
control bits that control the general property of the chip (see the description in MCUCR in detail). It
is a port, fully packed with 8 control bits with their own names (ISC00, ISC01, ...). Those who want
to send their AVR to a deep sleep need to know from the data sheet how to set the respective bits.
Like this:

.DEF MyPreferredRegister = R16


LDI MyPreferredRegister, 0b00100000
OUT MCUCR, MyPreferredRegister
SLEEP

The Out command brings the content of my preferred register, a Sleep-Enable-Bit called SE, to the
port MCUCR and sets the AVR immediately to sleep, if there is a SLEEP instruction executed. As all
the other bits of MCUCR are also set by the above instructions and the Sleep Mode bit SM was set to
zero, a mode called half-sleep will result: no further command execution will be performed but the
chip still reacts to timer and other hardware interrupts. These external events interrupt the big sleep of
the CPU if they feel they should notify the CPU.

Reading a port's content is in most cases possible using the IN command. The following sequence

.DEF MyPreferredRegister = R16


IN MyPreferredRegister, MCUCR

reads the bits in port MCUCR to the register. As many ports have undefined and unused bits in
certain ports, these bits always read back as zeros.

More often than reading all 8 bits of a port one must react to a certain status of a port. In that case we
don't need to read the whole port and isolate the relevant bit. Certain commands provide an
opportunity to execute commands depending on the level of a certain bit (see the JUMP section).
Setting or clearing certain bits of a port is also possible without reading and writing the other bits in
the port. The two commands are SBI (Set Bit I/o) and CBI (Clear Bit I/o). Execution is like this:

.EQU ActiveBit=0 ; The bit that is to be changed


SBI PortB, ActiveBit ; The bit will be set to one
CBI PortB, Activebit ; The bit will be cleared to zero

These two instructions have a limitation: only ports with an adress smaller than 0x20 can be handled,
ports above cannot be accessed that way.

For the more exotic programmer: the ports can be accessed using SRAM access commands, e.g. ST
and LD. Just add 0x20 to the port's adress (the first 32 addresses are the registers!) and access the port
that way. Like demonstrated here:

.DEF MyPreferredRegister = R16


LDI ZH,HIGH(PORTB+32)
LDI ZL,LOW(PORTB+32)
LD MyPreferredRegister,Z

That only makes sense in certain cases, but it is possible. It is the reason why the first address
location of the SRAM is always 0x60.

To the top of that page

Details of relevant ports in the AVR


The following table holds the most used ports. Not all ports are listed here, some of the MEGA and
AT90S4434/8535 types are skipped. If in doubt see the original reference. Ports:
Component Link Register Link
Accumulator SREG Status Register SREG
Stack SPL/SPH Stackpointer SPL/SPH
Ext.SRAM/
MCUCR MCU General Control Register MCUCR
Ext.Interrupt
Interrupt Mask Register GIMSK
Ext.Int. INT
Flag Register GIFR
Timer Int Mask Register TIMSK
Timer Interrupts Timer Int.
Timer Interrupt Flag Register TIFR
Timer/Counter 0 Control Register TCCR0
Timer 0 Timer 0
Timer/Counter 0 TCNT0
Timer/Counter Control Register 1 A TCCR1A
Timer/Counter Control Register 1 B TCCR1B
Timer/Counter 1 TCNT1
Timer 1 Timer 1
Output Compare Register 1 A OCR1A
Output Compare Register 1 B OCR1B
Input Capture Register ICR1L/H
Watchdog Timer WDT Watchdog Timer Control Register WDTCR
EEPROM Adress Register EEAR
EEPROM EEPROM EEPROM Data Register EEDR
EEPROM Control Register EECR
Serial Peripheral Control Register SPCR
SPI SPI Serial Peripheral Status Register SPSR
Serial Peripheral Data Register SPDR
UART Data Register UDR
UART Status Register USR
UART UART
UART Control Register UCR
UART Baud Rate Register UBRR
Analog Comparator ANALOG Analog Comparator Control and Status Register ACSR
I/O-Ports IO-Ports

To the top of that page

The status register as the most used port


By far the mostly used port is the status register with its 8 bits. Usually access to this port is only by
automatic setting and clearing bits by the CPU or accumulator, some access is by reading or
branching on certain bits in that port, in a few cases it is possible to manipulate these bits directly
(using the assembler command SEx or CLx, where x is the bit abbreviation). Most of these bits are
set or cleared by the accumulator through bit-test, compare- or calculation-operations. The following
list has all assembler commands that set or clear status bits depending on the result of the execution.
Bit Calculation Logic Compare Bits Shift Others
AND, ANDI,
BCLR Z,
ADD, ADC, ADIW, OR, ORI, ASR, LSL,
BSET Z,
Z DEC, INC, SUB, SUBI, EOR, COM, CP, CPC, CPI LSR, ROL, CLR
CLZ, SEZ,
SBC, SBCI, SBIW NEG, SBR, ROR
TST
CBR
ADD, ADC, ADIW, BCLR C, ASR, LSL,
C SUB, SUBI, SBC, COM, NEG CP, CPC, CPI BSET C, LSR, ROL, -
SBCI, SBIW CLC, SEC ROR
AND, ANDI,
BCLR N,
ADD, ADC, ADIW, OR, ORI, ASR, LSL,
BSET N,
N DEC, INC, SUB, SUBI, EOR, COM, CP, CPC, CPI LSR, ROL, CLR
CLN, SEN,
SBC, SBCI, SBIW NEG, SBR, ROR
TST
CBR
AND, ANDI,
BCLR V,
ADD, ADC, ADIW, OR, ORI, ASR, LSL,
BSET V,
V DEC, INC, SUB, SUBI, EOR, COM, CP, CPC, CPI LSR, ROL, CLR
CLV, SEV,
SBC, SBCI, SBIW NEG, SBR, ROR
TST
CBR
BCLR S,
S SBIW - - BSET S, - -
CLS, SES
BCLR H,
ADD, ADC, SUB,
H NEG CP, CPC, CPI BSET H, - -
SUBI, SBC, SBCI
CLH, SEH
BCLR T,
BSET T,
T - - - - -
BST, CLT,
SET
BCLR I,
I - - - BSET I, CLI, - RETI
SEI

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/PORTS.html1/20/2009 7:52:30 PM
Details of relevant ports in the AVR

Path: Home => AVR-overview => Assembler introduction => Ports => Details

Introduction to AVR assembler programming


for beginners
The table of the relevant ports in the ATMEL AVR types AT90S2313, 2323 and 8515. Bytewise
accessable ports or register pairs are not displayed in detail. No warranty for correctness, see the data
sheets!

Status-Register, Accumulator flags

Port Function Port-Address RAM-Address


SREG Status Register Accumulator 0x3F 0x5F

7 6 5 4 3 2 1 0
I T H S V N Z C

Bit Name Meaning Opportunities Conand


0: Interrupts disabled CLI
7 I Global Interrupt Flag
1: Interrupts enabled SEI
0: Stored bit is 0 CLT
6 T Bit storage
1: Stored bit is 1 SET
0: No halfcarry occured CLH
5 H Halfcarry-Flag
1: Halfcarry occured SEH
0: Sign positive CLS
4 S Sign-Flag
1: Sign negative SES
0: No carry occured CLV
3 V Two's complement-Flag
1: Carry occured SEV
0: Result was not negative/smaller CLN
2 N Negative-Flag
1: Result was negative/smaller SEN
0: Result was not zero/unequal CLZ
1 Z Zero-Flag
1: Result was zero/equal SEZ
0: No carry occured CLC
0 C Carry-Flag
1: Carry occured SEC

To the top of that page

Stackpointer

Port Function Port-Address RAM-Address


SPL/SPH Stackpointer 003D/0x3E 0x5D/0x5E

Name Meaning Verfügbarkeit


SPL Low-Byte of Stackpointer From AT90S2313 upwards, not in 1200
From AT90S8515 upwards, only in devices with >256 bytes
SPH High-Byte of Stackpointer
internal SRAM

To the top of that page

SRAM and External Interrupt control

Port Function Port-Address RAM-Address


MCUCR MCU General Control Register 0x35 0x55

7 6 5 4 3 2 1 0
SRE SRW SE SM ISC11 ISC10 ISC01 ISC00

Bit Name Meaning Opportunities


0=No external SRAM connected
7 SRE Ext.SRAM Enable
1=External SRAM connected
0=No extra wait state on external SRAM
6 SRW Ext.SRAM Wait States
1=Additional wait state on external SRAM
0=Ignore SLEEP commands
5 SE Sleep Enable
1=SLEEP on command
0=Idle Mode (Half sleep)
4 SM Sleep Mode
1=Power Down Mode (Full sleep)
00: Low-level initiates Interrupt
3 ISC11
Interrupt control Pin INT1 01: Undefined
(connected to GIMSK) 10: Falling edge triggers interrupt
2 ISC10
11: Rising edge triggers interrupt
00: Low-level initiates interrupt
1 ISC01
Interrupt control Pin INT0 01: Undefined
(connected to GIMSK) 10: Falling edge triggers interrupt
0 ISC00
11: Rising edge triggers interrupt

To the top of that page

External Interrupt Control

Port Function Port-Address RAM-Address


GIMSK General Interrupt Maskregister 0x3B 0x5B

7 6 5 4 3 2 1 0
INT1 INT0 - - - - - -

Bit Name Meaning Opportunities


Interrupt by external pin INT1 0: External INT1 disabled
7 INT1
(connected to mode in MCUCR) 1: External INT1 enabled

Interrupt by external Pin INT0 0: External INT0 disabled


6 INT0
(connected to mode in MCUCR) 1: External INT0 enabled
0...5 (Not used)

Port Function Port-Address RAM-Address


GIFR General Interrupt Flag Register 0x3A 0x5A

7 6 5 4 3 2 1 0
INTF1 INTF0 - - - - - -

Bit Name Meaning Opportunities


Interrupt by external pin INT1
7 INTF1
occured Automatic clear by execution of the Int-Routine or
Interrupt by external pin INT0 Clear by command
6 INTF0
occured
0...5 (Not used)

To the top of that page

Timer Interrupt Control

Port Function Port-Address RAM-Address


TIMSK Timer Interrupt Maskregister 0x39 0x59

7 6 5 4 3 2 1 0
TOIE1 OCIE1A OCIE1B - TICIE1 - TOIE0 -

Bit Name Meaning Opportunities


0: No Int at overflow
7 TOIE1 Timer/Counter 1 Overflow-Interrupt
1: Int at overflow
0: No Int at equal A
6 OCIE1A Timer/Counter 1 Compare A Interrupt
1: Int at equal A
0: No Int at B
5 OCIE1B Timer/Counter 1 Compare B Interrupt
1: Int at equal B
4 (Not used)
0: No Int at Capture
3 TICIE1 Timer/Counter 1 Capture Interrupt
1: Int at Capture
2 (Not used)
0: No Int at overflow
1 TOIE0 Timer/Counter 0 Overflow-Interrupt
1: Int at overflow
0 (Not used)

Port Function Port-Address RAM-Address


TIFR Timer Interrupt Flag Register 0x38 0x58

7 6 5 4 3 2 1 0
TOV1 OCF1A OCF1B - ICF1 - TOV0 -

Bit Name Meaning Opportunities


7 TOV1 Timer/Counter 1 Overflow reached Interrupt-Mode:
6 OCF1A Timer/Counter 1 Compare A reached Automatic Clear
5 OCF1B Timer/Counter 1 Compare B reached by execution of the
Int-Routine
4 (Not used)
3 ICF1 Timer/Counter 1 Capture-Event occured OR
2 (not used) Polling-Mode:
1 TOV0 Timer/Counter 0 Overflow occured Clear by
command
0 (not used)

To the top of that page

Timer/Counter 0

Port Function Port-Address RAM-Address


TCCR0 Timer/Counter 0 Control Register 0x33 0x53

7 6 5 4 3 2 1 0
- - - - - CS02 CS01 CS00

Bit Name Meaning Opportunities


000: Stop Timer
001: Clock = Chip clock
010: Clock = Chip clock / 8
011: Clock = Chip clock / 64
2..0 CS02..CS00 Timer Clock
100: Clock = Chip clock / 256
101: Clock = Chip clock / 1024
110: Clock = falling edge of external Pin T0
111: Clock = rising edge of external Pin T0
3..7 (not used)

Port Function Port-Address RAM-Address


TCNT0 Timer/Counter 0 count register 0x32 0x52

To the top of that page

Timer/Counter 1

Port Function Port-Address RAM-Address


TCCR1A Timer/Counter 1 Control Register A 0x2F 0x4F

7 6 5 4 3 2 1 0
COM1A1 COM1A0 COM1B1 COM1B0 - - PWM11 PWM10

Bit Name Meaning Opportunities


7 COM1A1
Compare Output A 00: OC1A/B not connected
6 COM1A0 01: OC1A/B changes polarity
5 COM1B1 10: OC1A/B to zero
Compare Output B 11: OC1A/B to one
4 COM1B0
3
(not used)
2
00: PWM off
PWM11 01: 8-Bit PWM
1..0 Pulse width modulator
PWM10 10: 9-Bit PWM
11: 10-Bit PWM

Port Function Port-Address RAM-Address


TCCR1B Timer/Counter 1 Control Register B 0x2E 0x4E

7 6 5 4 3 2 1 0
ICNC1 ICES1 - - CTC1 CS12 CS11 CS10

Bit Name Meaning Opportunities


Noise Canceler 0: disabled, first edge starts sampling
7 ICNC1
on ICP-Pin 1: enabled, min four clock cycles
Edge selection 0: falling edge triggers Capture
6 ICES1
on Capture 1: rising edge triggers Capture
5..4 (not used)
Clear at
3 CTC1 1: Counter set to zero if equal
Compare Match A
000: Counter stopped
001: Clock
010: Clock / 8
011: Clock / 64
2..0 CS12..CS10 Clock select
100: Clock / 256
101: Clock / 1024
110: falling edge external Pin T1
111: rising edge external Pin T1

Port Function Port-Address RAM-Address


TCNT1L/H Timer/Counter 1 count register 0x2C/0x2D 0x4C/0x4D

Port Function Port-Address RAM-Address


OCR1AL/H Timer/Counter 1 Output Compare register A 0x2A/0x2B 0x4A/0x4B hex

Port Function Port-Address RAM-Address


OCR1BL/H Timer/Counter 1 Output Compare register B 0x28/0x29 0x48/0x49

Port Function Port-Address RAM-Address


ICR1L/H Timer/Counter 1 Input Capture Register 0x24/0x25 0x44/0x45

To the top of that page

Watchdog-Timer

Port Function Port-Address RAM-Address


WDTCR Watchdog Timer Control Register 0x21 0x41

7 6 5 4 3 2 1 0
- - - WDTOE WDE WDP2 WDP1 WDP0

Bit Name Meaning WDT-cycle at 5.0 Volt


7..5 (not used)
Previous set to
4 WDTOE Watchdog Turnoff Enable
disabling of WDE required
3 WDE Watchdog Enable 1: Watchdog aktive
000: 15 ms
001: 30 ms
010: 60 ms
011: 120 ms
2..0 WDP2..WDP0 Watchdog Timer Prescaler
100: 240 ms
101: 490 ms
110: 970 ms
111: 1,9 s

To the top of that page

EEPROM

Port Function Port-Address RAM-Address


EEARL/H EEPROM Address Register 0x1E/0x1F 0x3E/0x3F
EEARH only in types with more than 256 Bytes EEPROM (from AT90S8515 upwards)

Port Function Port-Address RAM-Address


EEDR EEPROM Data Register 0x1D 0x3D

Port Function Port-Address RAM-Address


EECR EEPROM Control Register 0x1C 0x3C

7 6 5 4 3 2 1 0
- - - - - EEMWE EEWE EERE

Bit Name Meaning Function


7..3 (not used)
2 EEMWE EEPROM Master Write Enable Previous set enables write cycle
1 EEWE EEPROM Write Enable Set to initiate write
0 EERE EEPROM Read Enable Set initiates read

To the top of that page

Serial Peripheral Interface SPI

Port Function Port-Address RAM-Address


SPCR SPI Control Register 0x0D 0x2D

7 6 5 4 3 2 1 0
SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0

Bit Name Meaning Function


0: Interrupts disabled
7 SPIE SPI Interrupt Enable
1: Interrupts enabled
0: SPI disabled
6 SPE SPI Enable
1: SPI enabled
0: MSB first
5 DORD Data Order
1: LSB first
0: Slave
4 MSTR Master/Slave Select
1: Master
0: Positive Clock Phase
3 CPOL Clock Polarity
1: Negative Clock Phase
0: Sampling at beginning of Clock Phase
2 CPHA Clock Phase
1: Sampling at end of Clock Phase
00: Clock / 4
1 SPR1
01: Clock / 16
SCK clock frequency
10: Clock / 64
0 SPR0
11: Clock / 128

Port Function Port-Address RAM-Address


SPSR SPI Status Register 0x0E 0x2E

7 6 5 4 3 2 1 0
SPIF WCOL - - - - - -

Bit Name Meaning Function


7 SPIF SPI Interrupt Flag Interrupt request
6 WCOL Write Collision Flag Write collission occured
5..0 (not used)

Port Function Port-Address RAM-Address


SPDR SPI Data Register 0x0F 0x2F

To the top of that page

UART

Port Function Port-Address RAM-Address


UDR UART I/O Data Register 0x0C 0x2C

Port Function Port-Address RAM-Address


USR UART Status Register 0x0B 0x2B

7 6 5 4 3 2 1 0
RXC TXC UDRE FE OR - - -

Bit Name Meaning Function


7 RXC UART Receive Complete 1: Char received
6 TXC UART Transmit Complete 1: Shift register empty
5 UDRE UART Data Register Empty 1: Transmit register available
4 FE Framing Error 1: Illegal Stop-Bit
3 OR Overrun 1: Lost char
2..0 (not used)

Port Function Port-Address RAM-Address


UCR UART Control Register 0x0A 0x2A

7 6 5 4 3 2 1 0
RXCIE TXCIE UDRIE RXEN TXEN CHR9 RXB8 TXB8

Bit Name Meaning Function


7 RXCIE RX Complete Interrupt Enable 1: Interrupt on received char
6 TXCIE TX Complete Interrupt Enable 1: Interrupt at transmit complete
5 UDRIE Data Register Empty Interrupt Enable 1: Interrupt on transmit buffer empty
4 RXEN Receiver Enabled 1: Receiver enabled
3 TXEN Transmitter Enable 1: Transmitter enabled
2 CHR9 9-bit Characters 1: Char length 9 Bit
1 RXB8 Receive Data Bit 8 9th Data bit on receive
0 TXB8 Transmit Data Bit 8 9.Data bit on transmit

Port Function Port-Address RAM-Address


UBRR UART Baud Rate Register 0x09 0x29

To the top of that page

Analog Comparator

Port Function Port-Address RAM-Address


ACSR Analog Comparator Control and Status Register 0x08 0x28

7 6 5 4 3 2 1 0
ACD - ACO ACI ACIE ACIC ACIS1 ACIS0

Bit Name Meaning Function


7 ACD Disable Disable Comparators
6 (not used)
5 ACO Comparator Output Read: Output of the Comparators
4 ACI Interrupt Flag 1: Interrupt request
3 ACIE Interrupt Enable 1: Interrupts enabled
2 ACIC Input Capture Enable 1: Connect to Timer 1 Capture
00: Interrupt on edge change
1 ACIS1
01: not used)
Input Capture Enable
10: Interrupt on falling edge
0 ACIS0
11: Interrupt on rising edge

To the top of that page

I/O Ports

Port Register Function Port-Address RAM-Address


PORTA Data Register 0x1B 0x3B
A DDRA Data Direction Register 0x1A 0x3A
PINA Input Pins Address 0x19 0x39
PORTB Data Register 0x18 0x38
B DDRB Data Direction Register 0x17 0x37
PINB Input Pins Address 0x16 0x36
PORTC Data Register 0x15 0x35
C DDRC Data Direction Register 0x14 0x34
PINC Input Pins Address 0x13 0x33
PORTD Data Register 0x12 0x32
D DDRD Data Direction Register 0x11 0x31
PIND Input Pins Address 0x10 0x30

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/PDETAIL.html1/20/2009 7:52:36 PM
Program control in the AVR assembler language

Path: Home => AVR-overview => Assembler intro => Program control

Introduction to AVR assembler programming


for beginners
Controlling sequential execution of the program
Here we discuss all commands that control the sequential execution of a program. It starts with the
starting sequence on power-up of the processor, jumps, interrupts, etc.

What happens during a reset?

When the power supply of an AVR rises and the processor starts its work, the hardware triggers a
reset sequence. The counter for the program steps will be set to zero. At this address the execution
always starts. Here we have to have our first word of code. But not only during power-up this address
is activated:

1. During an external reset on the reset pin a restart is executed.


2. If the Watchdog counter reaches its maximum count, a reset is initiated. A watchdog timer is
an internal clock that must be resetted from time to time by the program, otherwise it restarts
the processor.
3. You can call reset by a direct jump to that address (see the jump section below).

The third case is not a real reset, because the automatic resetting of register- and port-values to a well-
defined default value is not executed. So, forget that for now.

The second option, the watchdog reset, must first be enabled by the program. It is disabled by default.
Enabling requires write commands to the watchdog's port. Setting the watchdog counter back to zero
requires the execution of the command

WDR

to avoid a reset.

After execution of a reset, with setting registers and ports to default values, the code at address 0000
is wordwise read to the execution part of the processor and is executed. During that execution the
program counter is already incremented by one and the next word of code is already read to the code
fetch buffer (Fetch during Execution). If the executed command does not require a jump to another
location in the program the next command is executed immediately. That is why the AVRs execute
extremely fast, each clock cycle executes one command (if no jumps occur).

The first command of an executable is always located at address 0000. To tell the compiler
(assembler program) that our source code starts now and here, a special directive can be placed at the
beginning, before the first code in the source is written:

.CSEG
.ORG 0000

The first directive lets the compiler switch to the code section. All following is translated as code and
is written to the program memory section of the processor. Another target segment would be the
EEPROM section of the chip, where you also can write bytes or words to.

.ESEG

The third segment is the SRAM section of the chip.

.DSEG

The ORG directive above stands for origin and manipulates the address within the code segment,
where assembled words go to. As our program always starts at 0x0000 the CSEG/ORG directives are
trivial, you can skip these without getting into an error. We could start at 0x0100, but that makes no
real sense. If you want to place a table exactly to a certain location of the code segment, you can use
ORG. If you want to set a clear sign within your code, after first defining a lot of other things with .
DEF- and .EQU-directives, use the CSEG/ORG sequence, even though it might not be necessary to
do that.

As the first code word is always at address zero, this location is also called the reset vector.
Following the reset vector the next positions in the program space, addresses 0x0001, 0x0002 etc.,
are interrupt vectors. These are the positions where the execution jumps to if an external or internal
interrupt has been enabled and occurs. These positions called vectors are specific for each processor
type and depend on the internal hardware available (see below). The commands to react to such an
interrupt have to be placed to the proper vector location. If you use interrupts, the first code, at the
reset vector, must be a jump command, to jump over the other vectors. Each interrupt vector must
hold a jump command to the respective interrupt service routine. The typical program sequence at the
beginning is like follows:

.CSEG
.ORG 0000
RJMP Start
RJMP IntServRout1
[...] here we place the other interrupt vector commands
[...] and here is a good place for the interrupt service routines themselves
Start: ; This here is the program start
[...] Here we place our main program

The command RJMP results in a jump to the label Start:, located some lines below. Labels always
start in column 1 of the source code and end with a :. Labels, that don't fulfil these conditions are not
taken for serious by the compiler. Missing labels result in an error message ("Undefined label"), and
compilation is interrupted.

To the top of this page

Linear program execution and branches

Program execution is always linear, if nothing changes the sequential execution. These changes are
the execution of an interrupt or of branching instructions.

Branching is very often depending on some condition, conditioned branching. As an example we


assume we want to construct a 32-bit-counter using registers R1 to R4. The least significant byte in
R1 is incremented by one. If the register overflows during that operation (255 + 1 = 0), we have to
increment R2 similiarly. If R2 overflows, we have to increment R3, and so on.

Incrementation by one is done with the instruction INC. If an overflow occurs during that execution
of INC R1 the zero bit in the status register is set to one (the result of the operation is zero). The carry
bit in the status register, usually set by overflows, is not changed during an INC. This is not to
confuse the beginner, but carry is used for other purposes instead. The Zero-Bit or Zero-flag is
enough to detect an overflow. If no overflow occurs we can just leave the counting sequence.

If the Zero-bit is set, we must execute additional incrementation of the other registers.To confuse the
beginner the branching command, that we have to use, is not named BRNZ but BRNE (BRanch if
Not Equal). A matter of taste ...

The whole count sequence of the 32-bit-counter should look like this:

INC R1
BRNE GoOn32
INC R2
BRNE GoOn32
INC R3
BRNE GoOn32
INC R4
GoOn32:

So that's about it. An easy thing. The opposite condition to BRNE is BREQ or BRanch EQual.

Which of the status bits, also called processor flags, are changed during execution of a command is
listed in instruction code tables, see the List of Instructions. Similiarly to the Zero-bit you can use the
other status bits like that:

BRCC/BRCS ; Carry-flag 0 oder 1


BRSH ; Equal or greater
BRLO ; Smaller
BRMI ; Minus
BRPL ; Plus
BRGE ; Greater or equal (with sign bit)
BRLT ; Smaller (with sign bit)
BRHC/BRHS ; Half overflow flag 0 or 1
BRTC/BRTS ; T-Bit 0 or 1
BRVC/BRVS ; Two's complement flag 0 or 1
BRIE/BRID ; Interrupt enabled or disabled

to react to the different conditions. Branching always occurs if the condition is met. Don't be afraid,
most of these commands are rarely used. For the beginner only Zero and Carry are relevant.

To the top of that page

Timing during program execution

Like mentioned above the required time to execute one instruction is equal to the processor's clock
cycle. If the processor runs on a 4 MHz clock frequency then one instruction requires 1/4 µs or
250 ns, at 10 MHz clock only 100 ns. The required time is as exact as the xtal clock. If you need
exact timing an AVR is the optimal solution for your problem. Note that there are a few commands
that require two or more cycles, e.g. the branching instructions (if branching occurs) or the SRAM
read/write sequence. See the instructions table for details.

To define exact timing there must be an opportunity that does nothing else than delay program
execution. You might use other instructions that do nothing, but more clever is the use of the No
OPeration command NOP. This is the most useless instruction:

NOP

This instruction does nothing but wasting processor time. At 4 MHz clock we need just four of these
instructions to waste 1 µs. No other hidden meanings here on the NOP instruction. For a signal
generator with 1 kHz we don't need to add 4000 such instructions to our source code, but we use a
software counter and some branching instructions. With these we construct a loop that executes for a
certain number of times and are exactly delayed. A counter could be a 8-bit-register that is
decremented with the DEC instruction, e.g. like this:

CLR R1
Count:
DEC R1
BRNE Count

16-bit counting can also be used to delay exactly, like this

LDI ZH,HIGH(65535)
LDI ZL,LOW(65535)
Count:
SBIW ZL,1
BRNE Count

If you use more registers to construct nested counters you can reach any delay. And the delay is
absolutely exact, even without a hardware timer.

To the top of that page

Macros and program execution

Very often you have to write identical or similiar code sequences on different occasions in your
source code. If you don't want to write it once and jump to it via a subroutine call you can use a
macro to avoid getting tired writing the same sequence serveral times. Macros are code sequences,
designed and tested once, and inserted into the code by its macro name. As an example we assume
we need to delay program execution several times by 1 µs at 4 MHz clock. Then we define a macro
somewhere in the source:

.MACRO Delay1
NOP
NOP
NOP
NOP
.ENDMACRO

This definition of the macro does not yet produce any code, it is silent. Code is produced if you call
that macro by its name:

[...] somewhere in the source code


Delay1
[...] code goes on here

This results in four NOP incstructions inserted to the code at that location. An additional Delay1
inserts additional four NOP instructions.

By calling a macro by its name you can add some parameters to manipulate the produced code. But
this is more than a beginner has to know about macros.

If your macro has longer code sequences, or if you are short in code storage space, you should avoid
the use of macros and use subroutines instead.

To the top of that page

Subroutines

In contrary to macros a subroutine does save program storage space. The respective sequence is only
once stored in the code and is called from whatever part of the code. To ensure continued execution
of the sequence following the subroutine call you need to return to the caller. For a delay of 10 cycles
you need to write this subroutine:

Delay10:
NOP
NOP
NOP
RET

Subroutines always start with a label, otherwise you would not be able to jump to it, here Delay10:.
Three NOPs follow and a RET instruction. If you count the necessary cycles you just find 7 cycles (3
for the NOPs, 4 for the RET). The missing 3 are for calling that routine:

[...] somewhere in the source code:


RCALL Delay10
[...] further on with the source code

RCALL is a relative call. The call is coded as relative jump, the relative distance from the calling
routine to the subroutine is calculated by the compiler. The RET instruction jumps back to the calling
routine. Note that before you use subroutine calls you must set the stackpointer (see Stack), weil die
because the return address must be packed on the stack by the RCALL instruction.

If you want to jump directly to somewhere else in the code you have to use the jump instruction:

[...] somewhere in the source code


RJMP Delay10
Return:
[...] further on with source code

The routine that you jumped to can not use the RET command in that case. To return back to the
calling location in the source requires to add another label and the called routine to jump back to this
label. Jumping like this is not like calling a subroutine because you can't call this routine from
different locations in the code.

RCALL and RJMP are unconditioned branches. To jump to another location, depending on some
condition, you have to combine these with branching instructions. Conditioned calling of a subroutine
can best be done with the following commands. If you want to call a subroutine depending on a
certain bit in a register use the following sequence:

SBRC R1,7 ; Skip the next instruction if bit 7 is 0


RCALL UpLabel ; Call that subroutine

SBRC reads Skip next instruction if Bit in Register is Clear. The RCALL instruction to UpLabel: is
only executed if bit 7 in register R1 is 1, because the next instruction is skipped if it would be 0. If
you like to call the subroutine in case this bit is 0 then you use the corresponding instruction SBRS.
The instruction following SBRS/SBRC can be a single word or double word instruction, the
processor knows how far he has to jump over it. Note that execution times are different then. To jump
over more than one following instruction these commands cannot be used.

If you have to skip an instruction if two registers have the same value you can use the following
exotic instruction

CPSE R1,R2 ; Compare R1 and R2, skip if equal


RCALL SomeSubroutine ; Call SomeSubroutine

A rarely used command, forget it for the beginning.

If you like to skip the following instruction depending on a certain bit in a port use the following
instructions SBIC und SBIS. That reads Skip if the Bit in I/o space is Clear (or Set), like this:

SBIC PINB,0 ; Skip if Bit 0 on port B is 0


RJMP ATarget ; Jump to the label ATarget

The RJMP-instruction is only executed ist bit 0 in port B is high. This is something confusing for the
beginner. The access to the port bits is limited to the lower half of ports, the upper 32 ports are not
usable here.

Now another exotic application for the expert. Skip this if you are a beginner. Assume we have a bit
switch with 4 switches connected to port B. Depending on the state of these 4 bits we would like to
jump to 16 different locations in the code. Now we can read the port and use several branching
instructions to find out, where we have to jump to today. As alternative you can write a table holding
the 16 addresses, like this:

MyTab:
RJMP Routine1
RJMP Routine2
[...]
RJMP Routine16

In our code we copy that adress of the table to the Z pointer register:

LDI ZH,HIGH(MyTab)
LDI ZL,LOW(MyTab)

and add the current state of the port B (in R16) to this address.

ADD ZL,R16
BRCC NoOverflow
INC ZH
NoOverflow:

Now we can jump to this location in the table, either for calling a subroutine:

ICALL

or as a jump with no way back:

IJMP

The processor loads the content of the Z register pair into its program counter and continues
operation there. More clever than branching over and over?

To the top of that page

Interrupts and program execution

Very often we have to react on hardware conditions or other events. An example is a change on an
input pin. You can program such a reaction by writing a loop, asking whether a change on the pin has
occurred. This method is called polling, its like running around in circles searching for new flowers.
If there are no other things to do and reaction time does not matter, you can do this with the
processor. If you have to detect short pulses of less than a µs duration this method is useless. In that
case you need to program an interrupt.

An interrupt is triggered by some hardware conditions. The condition has to be enabled first, all
hardware interrupts are disabled at reset time by default. The respective port bits enabling the
component's interrupt ability are set first. The processor has a bit in its status register enabling him to
respond to the interrupt of all components, the Interrupt Enable Flag. Enabling the general response
to interrupts requires the following command:

SEI ; Set Int Enable

If the interrupting condition occurs, e.g. a change on the port bit, the processor pushes the actual
program counter to the stack (which must be enabled first! See initiation of the stackpointer in Stack).
Without that the processor wouldn't be able to return back to the location, where the interrupt
occurred (which could be any time and anywhere). After that processing jumps to the predefined
location, the interrupt vector, and executes the instructions there. Usually this is a JUMP instruction
to the interrupt service routine somewhere in the code. The interrupt vector is a processor-specific
location and depending from the hardware component and the condition that leads to the interrupt.
The more hardware components and the more conditions, the more vectors. The different vectors for
some of the AVR types are listed in the following table. (The first vector isn't an interrupt but the
reset vector, performing no stack operation!)

Int Vector Address


Name triggered by ...
2313 2323 8515
RESET 0000 0000 0000 Hardware Reset, Power-On Reset, Watchdog Reset
INT0 0001 0001 0001 Level change on the external INT0-Pin
INT1 0002 - 0002 Level change on the external INT1-Pin
TIMER1 CAPT 0003 - 0003 Capture event on Timer 1
TIMER1 COMPA - - 0004 Timer1 = Compare A
TIMER1 COMPB - - 0005 Timer1 = Compare B
TIMER1 COMP1 0004 - - Timer1 = Compare 1
TIMER1 OVF 0005 - 0006 Timer1 Overflow
TIMER0 OVF 0006 0002 0007 Timer0 Overflow
SPI STC - - 0008 Serial transmit complete
UART RX 0007 - 0009 UART char in receive buffer available
UART UDRE 0008 - 000A UART transmitter ran empty
UART TX 0009 - 000B UART All sent
ANA_COMP - - 000C Analog Comparator

Note that the capability to react to events is very different for the different types. The addresses are
sequential, but not identical for different types. The higher a vector in the list the higher is its priority.
If two components have an interrupt condition at the same time the upmost vector with the lower
vector address wins. The lower int has to wait until the upper int was served. To disable lower ints
from interrupting during the execution of its service routine the first executed int disables the
processor's I-flag. The service routine must re-enable this flag after it is done with its job.

For re-setting the I status bit there are two ways. The service routine can end with the command:

RETI

This return from the int routine restores the I-bit after the return address has been loaded to the
program counter.

The second way is to enable the I-bit by the instruction

SEI ; Set Interrupt Enabled


RET ; Return

This is not the same as the RETI, because subsequent interrupts are already enabled before the
program counter is loaded with the return address. If another int is pending, its execution is already
starting before the return address is popped from the stack. Two or more nested addresses remain on
the stack. No bug is to be expected, but it is an unnecessary risk doing that. So just use the RETI
instruction to avoid this unnecessary flow to the stack.

An Int-vector can only hold a relative jump instruction to the service routine. If a certain int is not
used or undefined we can just put a RETI instruction there, in case a false int happens.

As further execution of lower-priority ints is blocked, all int service routines should be short. If you
need to have a longer routine to serve the int, use one of the two following methods. The first is to
allow ints by SEI within the service routine, whenever you're done with the most urgent tasks. Not
very clever. More convenient is to perform the urgent tasks, setting a flag somewhere in a register for
the slower reactions and return from the int immediately.

A very hard rule for int service routines is: First instruction is to save the status register on the stack,
before you use instructions that might change flags in the status register. The interrupted main
program might just be in a state using the flag for a branch decision, and the int would just change
that flag to another state. Funny things would happen from time to time. The last instruction before
the RETI therefore is to pop the status register content from the stack and restore its original content,
prior to the int.

For the same reason all used registers in a service routine should either be exclusively reserved for
that purpose or saved on stack and restored at the end of the service routine. Never change the content
of a register within a int service routine that is used somewhere else in the normal program without
restoring it.

Because of these basic requirements a more sophisticated example for an interrupt service routine
here.

.CSEG ; Code-Segment starts here


.ORG 0000 ; Address is zero
RJMP Start ; The reset-vector on Address 0000
RJMP IService ; 0001: first Int-Vektor, INT0 service routine
[...] here other vectors

Start: ; Here the main program starts


[...] here is enough space for defining the stack and other things

IService: ; Here we start with the Interrupt-Service-Routine


PUSH R16 ; save a register to stack
IN R16,SREG ; read status register
PUSH R16 ; and put on stack
[...] Here the Int-Service-Routine does something and uses R16
POP R16 ; get previous flag register from stack
OUT SREG,R16 ; restore old status
POP R16 ; get previous content of R16 from the stack
RETI ; and return from int

Looks a little bit complicated, but is a prerequisite for using ints without producing serious bugs. Skip
PUSH R16 and POP R16 if you can afford reserving R16 for exclusive use in that service routine.

That's it for the beginner. There are some other things with ints, but this is enough to start with, and
not to confuse you.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/JUMP.html1/20/2009 7:52:45 PM
Calculations AVR Assembler language

Path:Home => AVR-overview => assembler introduction => Calculations

Beginner's introduction to AVR assembler


language
Calculations in assembler language
Here we discuss all necessary commands for calculating in AVR assembler language. This includes
number systems, setting and clearing bits, shift and rotate, and adding/subtracting/comparing and the
format conversion of numbers.

Number systems in assembler

The following formats of numbers are common in assembler:

● Positive whole numbers (Integers),


● Signed whole numbers,
● Binary Coded Digits, BCD,
● Packed BCDs,
● ASCII-formatted numbers.

Positive whole numbers (integers)

The smallest whole number to be handled in assembler is a byte with eight bits. This codes numbers
between 0 and 255. Such bytes fit exactly into one register of the MCU. All bigger numbers must be
based on this basic format, using more than one register. Two bytes yield a word (range from 0 ..
65,535), three bytes form a longer word (range from 0 .. 16,777,215) and four bytes form a double
word (range from 0 .. 4,294,967,295).

The single bytes of a word or a double word can be stored in whatever register you prefer. Operations
with these single bytes are programmed byte by byte, so you don't have to put them in a row. In order
to form a row for a double word we could store it like this:

.DEF r16 = dw0


.DEF r17 = dw1
.DEF r18 = dw2
.DEF r19 = dw3

dw0 to dw3 are in a row in the registers. If we need to initiate this double word at the beginning of an
application (e.g. to 4,000,000), this should look like this:

.EQU dwi = 4000000 ; define the constant


LDI dw0,LOW(dwi) ; The lowest 8 bits to R16
LDI dw1,BYTE2(dwi) ; bits 8 .. 15 to R17
LDI dw2,BYTE3(dwi) ; bits 16 .. 23 to R18
LDI dw3,BYTE4(dwi) ; bits 24 .. 31 to R19

So we have splitted this decimal number called dwi to its binary portions and packed them into the
four byte packages. Now you can calculate with this double word.

To the top of that page

Signed numbers

Sometimes, but in rare cases, you need negative numbers to calculate with. A negative number is
defined by interpreting the most significant bit of a byte as sign bit. If it is 0 the number is positive. If
it is 1 the number is negative. If the number is negative we usually do not store the rest of the number
as is, but we use its inverted value. Inverted means that -1 as an byte integer is not written as
1,0000001 but as 1,1111111 instead. That means: subtract 1 from 0 and forget the overflow. The first
bit is the sign bit, signalling that this is a negative number. Why this different format (subtracting the
negative number from 0) is used is easy to understand: adding -1 (1,1111111) and +1 (0,0000001)
yields exactly zero, if you forget the overflow that occurs during that operation (the nineth bit).

In one byte the biggest number to be handled is +127 (binary 0,1111111), the smallest one is -128
(binary 1,0000000). In other computer languages this number format is called short integer. If you
need a bigger range of values you can add another byte to form a normal integer value, ranging from
+32,767 .. -32,768), four bytes provide a range from +2,147,483,647 .. -2,147,483,648, usually called
a LongInt or DoubleInt.

To the top of that page

Binary Coded Digits, BCD

Positive or signed whole numbers in the formats discussed above use the available space most
effectively. Another, less dense number format, but easier to handle is to store decimal numbers in a
byte for one digit each. The decimal digit is stored in its binary form in a byte. Each digit from 0 .. 9
needs four bits (0000 .. 1001), the upper four bits of the byte are zeros, blowing a lot of air into the
byte. For to handle the value 250 we would need at least three bytes, e.g.:
Bit value 128 64 32 16 8 4 2 1
Instructions to use:
R16, Digit 1 = 2 0 0 0 0 0 0 1 0 LDI R16,2
R17, Digit 2 = 5 0 0 0 0 0 1 0 1 LDI R17,5
LDI R18,0
R18, Digit 3 = 0 0 0 0 0 0 0 0 0

You can calculate with these numbers, but this is a bit more complicated in assember than calculating
with binary values. The advantage of this format is that you can handle as long numbers as you like,
as long as you have enough storage space. The calculations are as precise as you like (if you program
AVRs for banking applications), and you can convert them very easily to character strings.

To the top of that page

Packed BCDs

If you pack two decimal digits into one byte you don't loose that much storage space. This method is
called packed binary coded digits. The two parts of a byte are called upper and lower nibble. The
upper nibble usually holds the more significant digit, which has advantages in calculations (special
instructions in AVR assembler language). The decimal number 250 would look like this when
formatted as a packed BCD:
Byte Digits Value 8 4 2 1 8 4 2 1
Instructions for setting:
2 4,3 02 0 0 0 0 0 0 1 0 LDI R17,0x02 ; Upper byte
1 2,1 50 0 1 0 1 0 0 0 0 LDI R16,0x50 ; Lower byte

To set this correct you can use the binary notation (0b...) or the hexadecimal notation (0x...) to set the
proper bits to their correct nibble position.

Calculating with packed BCDs is a little more complicated compared to the binary form. Format
changes to character strings are as easy as with BCDs. Length of numbers and precision of
calculations is only limited by the storage space.

To the top of that page

Numbers in ASCII-format

Very similiar to the unpacked BCD format is to store numbers in ASCII format. The digits 0 to 9 are
stored using their ASCII (ASCII = American Standard Code for Information Interchange)
representation. ASCII is a very old format, develloped and optimized for teletype writers,
unnecessarily very complicated for computer use (do you know what a char named End Of
Transmission EOT meant when it was invented?), very limited in range for other than US languages
(only 7 bits per character), still used in communications today due to the limited efforts of some
operating system programmers to switch to more effective string systems. The ancient system is only
topped by the european 5-bit long teletype character set called Baudot set or the still used Morse code.

Within the ASCII code system the decimal digit 0 is represented by the number 48 (hex 0x30, binary
0b0011.0000), digit 9 is 57 decimal (hex 0x39, binary 0b0011.1001). ASCII wasn't designed to have
these numbers on the beginning of the code set as there are already command chars like the above
mentioned EOT for the teletype. So we still have to add 48 to a BCD (or set bit 4 and 5 to 1) to
convert a BCD to ASCII. ASCII formatted numbers need the same storage space like BCDs. Loading
250 to a register set representing that number would look like this:

LDI R18,'2'
LDI R17,'5'
LDI R16,'0'

The ASCII representation of these characters are written to the registers.

To the top of that page

Bit manipulations

To convert a BCD coded digit to its ASCII representation we need to set bit 4 and 5 to a one. In other
words we need to OR the BCD with a constant value of hex 0x30. In assembler this is done like this:

ORI R1,0x30

If we have a register that is already set to hex 0x30 we can use the OR with this register to convert
the BCD:

OR R1,R2

Back from an ASCII character to a BCD is a bit more complicated in AVR assembler, because the
instruction

ANDI R1,0x0F

that isolates the lower four bits (= the lower nibble) is only possible with registers above R15. If you
need to do this, use one of the registers R16 to R31!

If the hex value 0x0F is already in register R2, you can AND the ASCII character with this register:

AND R1,R2

The other instructions for manipulating bits in a register are also limited for registers above R15.
They would be formulated like this:

SBR R16,0b00110000 ; Set bits 4 und 5 to one


CBR R16,0b00110000 ; Clear bits 4 and 5 to zero

If one or more bits of a byte have to be inverted you can use the following instruction (which is not
possible for use with a constant):

LDI R16,0b10101010 ; Invert all even bits


EOR R1,R16 ; in register R1 and store result in R1

To invert all bits of a byte is called the One's complement:

COM R1

inverts the content in register R1 and replaces zeros by one and vice versa. Different from that is the
Two's complement, which converts a positive signed number to its negative complement (subracting
from zero). This is done with the instruction

NEG R1

So +1 (decimal: 1) yields -1 (binary 1.1111111), +2 yields -2 (binary 1.1111110), and so on.

Besides the manipulation of the bits in a register copying a single bit is possible using the so-called T-
bit of the status register. With

BLD R1,0

the T-bit is loaded to bit 0 of register R1. The T-bit can be set or cleared and then copy its content to
any bit in any register:

CLT ; clear T-bit, or


SET ; set T-bit, or
BST R2,2 ; copy register R2, bit 2, to the T-bit

To the top of that page

Shift and rotate

Shifting and rotating of binary numbers means multiplicating and dividing them by 2. Shifting has
several sub-instructions.

Multiplication with 2 is easily done by shifting all bits of a byte one binary digit left and writing a
zero to the least significant bit. This is called logical shift left. The former bit 7 of the byte will be
shiftet to the carry bit in the status register.

LSL R1

The inverse division by 2 is the instruction called logical shift right.

LSR R1

The former bit 7, now shifted to bit 6, is filled with a 0, while the former bit 0 is shifted into the carry
bit of the status register. This carry bit could be used to round up and down (if set, add one to the
result). Example, division by four with rounding:

LSR R1 ; division by 2
BRCC Div2 ; Jump if no round up
INC R1 ; round up
Div2:
LSR R1 ; Once again division by 2
BRCC DivE ; Jump if no round up
INC R1 ; Round Up
DivE:

So, dividing is easy with binaries as long as you divide by multiples of 2.

If signed integers are used the logical shift right would overwrite the sign-bit in bit 7. The instruction
arithmetic shift right leaves bit 7 untouched and shifts the 7 lower bits, inserting a zero in bit 6.

ASR R1

Like with logical shifting the former bit 0 goes to the carry bit in the status register.

What about multiplying a 16-bit word by 2? The most significant bit of the lower byte has to be
shifted to yield the lowest bit of the upper byte. In that step a shift would set the lowest bit to zero,
but we need to shift the carry bit from the previous shift of the lower byte into bit 0. This is called a
rotate. During rotation the carry bit in the status register is shifted to bit 0, the former bit 7 is shifted
to the carry during rotation.

LSL R1 ; Logical Shift Left of the lower byte


ROL R2 ; ROtate Left of the upper byte

The logical shift left in the first instruction shifts bit 7 to carry, the ROL instruction rolls it to bit 0 of
the upper byte. Following the second instruction the carry bit has the former bit 7. The carry bit can
be used to either indicate an overflow (if 16-bit-calculation is performed) or to roll it into upper bytes
(if more than 16 bit calculation is done).

Rolling to the right is also possible, dividing by 2 and shifting carry to bit 7 of the result:

LSR R2 ; Logical Shift Right, bit 0 to carry


ROR R1 ; ROtate Right and shift carry in bit 7

It's easy dividing with big numbers. You see that learning assembler is not THAT complicated.

The last instruction that shifts four bits in one step is very often used with packed BCDs. This
instruction shifts a whole nibble from the upper to the lower position and vice versa. In our example
we need to shift the upper nibble to the lower nibble position. Instead of using

ROR R1
ROR R1
ROR R1
ROR R1

we can perform that with a single

SWAP R1

This exchanges the upper and lower nibble. Note that the upper nibble's content will be different after
applying these two methods.

To the top of that page

Adding, subtracting and comparing

The following calculation operations are too complicated for the beginners and demonstrate that
assembler is only for extreme experts, hi. Read on your own risk!

To start complicated we add two 16-bit-numbers in R1:R2 and R3:R4. In this notation we mean that
the first register is the most signifant byte, the second the least significant.

ADD R2,R4 ; first add the two low-bytes


ADC R1,R3 ; then the two high-bytes

Instead of a second ADD we use ADC in the second instruction. That means add with carry, which is
set or cleared during the first instruction, depending from the result. Already scared enough by that
complicated math? If not: take this!

We subtract R3:R4 from R1:R2.

SUB R2,R4 ; first the low-byte


SBC R1,R3 ; then the high-byte

Again the same trick: during the second instruction we subract another 1 from the result if the result
of the first instruction had an overflow. Still breathing? If yes, cope with the following!

Now we compare a 16-bit-word in R1:R2 with the one in R3:R4 to evaluate whether it is bigger than
the second one. Instead of SUB we use the compare instruction CP, instead of SBC we use CPC:

CP R2,R4 ; compare lower bytes


CPC R1,R3 ; compare upper bytes

If the carry flag is set now, R1:R2 is bigger than R3:R4.

Now we add some more complicated stuff. We compare the content of R16 with a constant:
0b10101010.

CPI R16,0xAA

If the Zero-bit in the status register is set after that, we know that R16 is 0xAA. If the carry-bit is set,
we know, it is smaller. If it is not set and the Zero-bit is not set either, we know it is bigger.

And now the most complicated test. We evaluate whether R1 is zero or negative:

TST R1

If the Z-bit is set the register R1 is zero and we can follow with the instructions BREQ, BRNE,
BRMI, BRPL, BRLO, BRSH, BRGE, BRLT, BRVC or BRVS to branch around a bit.

Still with us? If yes, here is some packed BCD calculations. Adding two packed BCDs can result in
two different overflows. The usual carry shows an overflow, if the higher of the two nibbles
overflows to more than 15 decimal. Another overflow, from the lower to the upper nibble occurs, if
the two lower nibbles add to more than 15 decimal. To take an example we add the packed BCDs 49
(=hex 49) and 99 (=hex 99) to yield 148 (=hex 0x148). Adding these in binary math, results in a byte
holding hex 0xE2, no byte overflow occurs. The lower of the two nibbles has had an overflow
because 9+9=18 and the lower nibble can only handle numbers up to 15. The overflow was added to
bit 4, the lowest significant bit of the upper nibble. Which is correct! But the lower nibble should be 8
and is only 2 (18 = 0b0001.0010). We should add 6 to that nibble to yield a correct result. Which is
quite logic, because whenever the lower nibble reaches more than 9 we have to add 6 to correct that
nibble.
The upper nibble is totally incorrect, because it is 0xE and should be 3 (with a 1 overflowing to the
next upper digit of the packed BCD). If we add 6 to this 0xE we get to 0x4 and the carry is set
(=0x14). So the trick is to add these two numbers and then add 0x66 to correct the 2 digits of the
packed BCD. But halt: what if adding the first and the second number would not result in an overflow
to the upper nibble? And not result in a digit above 9 in the lower nibble? Adding 0x66 would then
result in a totally incorrect result. The lower 6 should only be added if the lower nibble either
overflows to the upper nibble or results in a digit greater than 9. The same with the upper nibble.
How do we know, if an overflow from the lower to the upper nibble has occurred? The MCU sets a
H-bit in the status register, the half-carry bit. The following table shows the different cases that are
possible after adding R1 and R2 and adding hex 0x66 after that.
Add R1,R2 Add Nibble,6
Correction
(Half)Carry-Bit (Half)Carry-Bit
0 0 subtract 6
1 0 none
0 1 none
1 1 (not possible)
To program an example we assume that the two packed BCDs are in R2 and R3, R1 will hold the
overflow, and R16 and R17 are available for calculations. R16 is the adding register for adding 0x66
(the register R2 cannot add a constant value), R17 is used to correct the result depending from the
different flags. Adding R2 and R3 goes like that:

LDI R16,0x66 ; for adding 0x66 to the result


LDI R17,0x66 ; for later subtracting from the result
ADD R2,R3 ; add the two two-digit-BCDs
BRCC NoCy1 ; jump if no byte overflow occurs
INC R1 ; increment the next higher byte
ANDI R17,0x0F ; don't subtract 6 from the higher nibble
NoCy1:
BRHC NoHc1 ; jump if no half-carry occured
ANDI R17,0xF0 ; don't subtract 6 from lower nibble
NoHc1:
ADD R2,R16 ; add 0x66 to result
BRCC NoCy2 ; jump if no carry occured
INC R1 ; increment the next higher byte
ANDI R17,0x0F ; don't subtract 6 from higher nibble
NoCy2:
BRHC NoHc2 ; jump if no half-carry occured
ANDI R17,0xF0 ; don't subtract 6 from lower nibble
NoHc2:
SUB R2,R17 ; subtract correction

A little bit shorter than that:

LDI R16,0x66
ADD R2,R16
ADD R2,R3
BRCC NoCy
INC R1
ANDI R16,0x0F
NoCy:
BRHC NoHc
ANDI R16,0xF0
NoCy:
SUB R2,R16

Question to think about: Why is that equally correct and where is the trick?

To the top of that page

Format conversion for numbers

All number formats can be converted to any other format. The conversion from BCD to ASCII and
vice versa was already shown above (Bit manipulations).

Conversion of packed BCDs is not very complicated either. First we have to copy the number to
another register. With the copied value we change nibbles with SWAP to exchange the upper and the
lower one. The upper part is cleared, e.g. by ANDing with 0x0F. Now we have the BCD of the upper
nibble and we can either use as is or set bit 4 and 5 to convert to an ASCII character. After that we
copy the byte again and treat the lower nibble without first SWAPping and get the lower BCD.

A little bit more complicated is the conversion of BCD digits to a binary. Depending on the numbers
to be handled we first clear the necessary bytes that will hold the result of the conversion. We then
start with the highest BCD digit. Before adding this to the result we multiply the result with 10. In
order to do this we copy the result to somewhere else. Then we multiply the result by four (two left
shifts resp. rolls). Adding the previously copied result to this yields a multiplication with 5. Now a
mulitiplication with 2 (left shift/roll) yields the 10-fold of the result. Now we add the BCD and repeat
that algorithm until all decimal digits are converted. If, during one of these operations, there occurs a
carry of the result, the BCD is too big to be converted.

The conversion of a binary to BCDs is even more complicated than that. If we convert a 16-bit-binary
we can subtract 10,000, until an overflow occurs, yielding the first digit. Then we repeat that with
1,000 to yield the second digit. And so on with 100 and 10, then the remainder is the last digit. The
constants 10,000, 1,000, 100 and 10 can be placed to the program memory storage in a wordwise
organised table, like this:

DezTab:
.DW 10000, 1000, 100, 10

and can be read wordwise with the LPM instruction from the table.

An alternative is a table that holds the decimal value of each bit in the 16-bit-binary, e.g.

.DB 0,3,2,7,6,8
.DB 0,1,6,3,8,4
.DB 0,0,8,1,9,2
.DB 0,0,4,0,9,6
.DB 0,0,2,0,4,8 ; and so on until
.DB 0,0,0,0,0,1

Then you shift the single bits of the binary left out of the registers to the carry. If it is a one, you add
the number in the table to the result by reading the numbers from the table using LPM. This is more
complicated to program and a little bit slower than the above method.

A third method is to calculate the table value, starting with 000001, by adding this BCD with itself,
each time after you have shifted a bit from the binary to the right and added the BCD.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/CALC.html1/20/2009 7:52:49 PM
Beginner's hardware for learning AVR assembler

Pfad: Home => AVR-english => Beginner => Hardware

Hardware for AVR-Assembler-Programming

Learning assembler requires some simple hardware equipment to test your programs and see, if it works in practice.

This page shows two easy schematics that enable you to homebrew the required hardware and gives you the necessary hints on the required background. This hardware really is easy to build. I know nothing easier than that to test your first software steps. If you like to make more experiments, leave some more space for future extensions on your
experimental board.

If you don't like the smell of soldering, you can buy a ready-to-use board, too. The available boards are characterised on this page below.

To the top of this page

The ISP-Interface of the AVR-processor family


Before going into practice, we have to learn a few essentials on the serial programming mode of the AVR family. No, you don't need three different voltages to program and read an AVR flash memory. No, you don't need another microprocessor to program the AVRs. No, you don't need 10 I/O lines to tell the chip what you like it to do. And you don't even
have to remove the AVR from your experimental board, before programming it. It's even easier than that.

All this is done by a build-in interface in the AVR chip, that enables you to write and read the content of the program flash and the built-in-EEPROM. This interface works serially and needs three signal lines:

● SCK: A clock signal that shifts the bits to be written to the memory into an internal shift register, and that shifts out the bits to be read from another internal shift register,
● MOSI: The data signal that sends the bits to be written to the AVR,
● MISO: The data signal that receives the bits read from the AVR.

These three signal pins are internally connected to the programming machine only if you change the RESET (sometimes also called RST or restart) pin to zero. Otherwise, during normal operation of the AVR, these pins are programmable I/O lines like all the others. If you like to use these pins for other purposes during normal operation, and for in-system-
programming, you'll have to take care, that these two purposes do not conflict. Usually you then decouple these by resistors or by use of a multiplexer. What is necessary in your case, depends from your use of the pins in the normal operation mode. ou're lucky, if you can use them for in- system-programming exclusively. Not necessary, but recommendable
for in-system-programming is, that you supply the programming hardware out of the supply voltage of your system. That makes it easy, and requires two additional lines between the programmer and the AVR board. GND is the common ground, VTG (target voltage) the suplly voltage (usually 5.0 volts). This adds up to 6 lines
between the programmer and the AVR board. The resulting ISP6 connection is, as defined by AMEL, shown left.

Standards always have alternative standards, that were used earlier. This is the technical basis that constitutes the adaptor industry. In our case the alternative standard was designed as ISP10 and was used on the STK200 board. It's still a very widespread standard, and even the STK500 is still equipped with it. ISP10 has an additional
signal to drive a red LED. This LED signals that the programmer is doing his job. A good idea. Just connect the LED to a resistor and clamp it the positive supply voltage.

To the top of this page

Programmer for the PC-Parallel-Port


Now, heat up your soldering iron and build up your programmer. It is a quite easy schematic and works with standard parts from your well-sorted experiments box.

Yes, that's all you need to program an AVR. The 25-pin plug goes into the parallel port of your PC, the 10-pin-ISP goes to your AVR experimental board. If your box doesn't have a 74LS245, you can also use a 74HC245 or a 74LS244/74HC244 (by changing some
pins and signals). If you use HC, don't forget to tie unused inputs either to GND or the supply voltage, otherwise the buffers might produce extra noise by capacitive switching.

The necessary program algorithm is done by the ISP software, that is available from ATMEL's software download page, by PonyProg2000 or other programmer software. Please be aware that the programmer software must support your device type.

To the top of that page

Experimental board with ATtiny13


This is a very small board that allows experiments with the ATtiny13's internal hardware.

Th

picture shows

● the ISP10 programming interface on the left, with a programming LED attached via a resistor of 390 Ohms,
● the ATtiny13 with a pull-up of 10k on its RESET pin (pin 1),
● the supply part with a bridge rectifier, to be supplied with 9..15V from an AC or DC source, and a
● small 5V regulator.

The ATtiny13 requires no external XTAL or clock generator, because it works with its internal 9.6 Mcs/s RC
generator and, by default, with a clock divider of 8 (clock frequency 1.2 Mcs/s). The hardware can be build
on a small board like the one shown in the picture. All pins of the tiny13 are accessible, and external
hardware components, like the LED shown, can be easily plugged in. This board allows the use of the
ATtn13's hardware components like I/O-ports, timers, AD converters, etc.

Experimental board with a AT90S2313/ATtiny2313


For test purposes we use a AT90S2313 or its compatible and more modern ATtiny2313 on an experimental
board. The schematic shows

● a small voltage supply for connection to an AC transformer and a voltage regulator 5V/1A,
● a XTAL clock generator (here with a 10 Mcs/s, all other frequencies below the maximum for the 2313 will also work),
● the necessary parts for a safe reset during supply voltage switching,
● the ISP-Programming-Interface (here with a ISP10PIN-connector).

So that's what you need to start with. Connect other peripheral add-ons to the numerous free I/O pins of the 2313.

The easiest output device can be a LED, connected via a resistor to the positive supply voltage. With that, you can start writing your first assembler program switching the LED on and off.

To the top of that page

Ready-to-use commercial programming boards for the AVR-family


If you do not like homebrewed hardware, and if have some extra money left that you don't know what to do with, you can buy a commercial programming board. Easy to get is the STK500 (e.g. from ATMEL. It has the following hardware:

● Sockets for programming most of the AVR types,


● serial und parallel programming,
● ISP6PIN- and ISP10PIN-connector for external In-System-Programming,
● programmable oscillator frequency and suplly voltages,
● plug-in switches and LEDs,
● a plugged RS232C-connector (UART),
● a serial Flash-EEPROM,
● access to all ports via a 10-pin connector.

Experiments can start with the also supplied AT90S8515. The board is connected to the PC using a serial port (COMx) and is controlled by later versions of AVR studio, available from ATMEL's webpage. This covers all hardware requirements that the beginner might have.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/HARDWARE.html1/20/2009 7:52:54 PM
Why learn and use assembler to program AVR chips?

Path: Home => AVR-overview => Assembler intro => Why assembler?

Programming in assembler for starters


Assembler or other languages, that is the question. Why should I learn another language, if I already
learned other programming languages? The best argument: while you live in France you are able to
get through by speaking english, but you will never feel at home then, and life remains complicated.
You can get through with this, but it is rather inappropriate. If things need a hurry, you should use the
country's language.

Short and easy


Assembler commands translate one by one to executed machine commands. The processor needs
only to execute what you want it to do and what is necessary to perform the task. No extra loops and
unnecessary features blow up the generated code. If your program storage is short and limited and
you have to optimize your program to fit into memory, assembler is choice 1. Shorter programs are
easier to debug, every step makes sense.

To the top of this page

Fast and quick


Because only necessary code steps are executed assembly programs are as fast as possible. The
duration of every step is known. Time critical applications, like time measurements without a
hardware timer, that should perform excellent, must be written in assembler. If you have more time
and don't mind if your chip remains 99% in a wait state type of operation you can choose any
language you want.

Assembler is easy to learn


It is not true that assmbly language is more complicated or not as easy to understand than other
languages. Learning assembly language for whatever hardware type brings you to understand the
basic concepts of any assembly language. Adding other dialects later is easy. The first assembly code
does not look very attractive, with every 100 additional lines programmed it looks better. Perfect
programs require some thousand lines of code of exercise and optimization requires lots of work. As
some features are hardware-dependant optimal code requires some familiarity with the hardware
concept and the dialect. The first steps are hard in any language. After some weeks of programming
you will laugh if you go through your first code. Some assembler commands need some monthes of
experience.

To the top of this page

AT90Sxxxx are ideal for learning assembler


Assembler programs are a little bit silly: the chip executes anything you tell it to do and does not ask
you if you are sure overwriting this and that. All protections must be programmed by you, the chip
does anything like it is told. No window warns you, unless you programmed it before. Basic design
errors are as complicated to debug like in any other computer language. But: testing programs on
ATMEL chips is very easy. If it does not do what you expect it to do you can easily add some
diagnostic lines to the code, reprogram the chip and test it. Bye, bye to you EPROM programmers, to
the UV lamps used to erase your test program, to you pins that don't fit into the socket after having
them removed some douzend times. Changes are now programmed fast, compiled in no time, and
either simulated in the studio or checked in-circuit. No pin is removed, and no UV lamp gives up just
in the moment when you had your excellent idea about that bug.

To the top of this page

Test it!
Be patient doing your first steps! If you are familiar with another language: forget it for the first time.
Behind every assembler language there is a certain hardware concept. Most of the special features of
other computer languages don't make any sense in assembler. The first five commands are not easy to
learn, then your learning speed rises fast. After you had your first lines: grab the instruction set list
and lay back in the bathtub, wondering what all the other commands are like. Don't try to program a
mega- machine to start with. This does not make sense in any computer language, and just produces
frustration. Comment your subroutines and store them in a special directory, if debugged: you will
need them again in a short time. Have success!

To the top of this page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/WHY.html1/20/2009 7:52:56 PM
Tools for AVR assembly programing

Path: Home => english => Assembler intro => tools

Tools for AVR assembly programing


This page provides informations about the necessary tools that are used to program AVRs with the
STK200 board. Programming with the STK500 is very different and shown in more detail in the
Studio section.
The older software for the STK200 is not supported any more. Four programs are necessary for this.
These tools are:

1. the editor,
2. the assembler program,
3. the chip programing interface, and
4. the simulator.

The necessary software tools are ©ATMEL and available on the webpage of ATMEL for download.
The screenshots here are © ATMEL. It should be mentioned that there are different versions of the
software and some of the screenshots are subject to change with the used version. Some windows or
menues look different in different versions. The basic functions are mainly unchanged. Refer to the
programer's handbook, this page just provides an overview for the beginner's first steps and is not
written for the assembly programing expert.

To the top of this page

The editor
Assembler programs are written with a editor. The editor just has to be able to create and edit ASCII
text files. So, basically, any simple editor does it. I recommend the use of a more advanced editor,
either WAVRASM©ATMEL or the editor written by Tan Silliksaar (screenshot see below).

An assembly program written with WAVRASM© goes like this. Just install WAVRASM© and start
the program:

Now we type in our directives and assembly commands in the WAVRASM editor window, together
with some comments (starting with ;). That should look like this:

Now store the program text, named to something.asm into a dedicated directory, using the file menue.
The assembly program is complete now.

If you like editing a little more in a sophisticated manner you can use the excellent editor written by
Tan Silliksaar. This editor tools is designed for AVRs and available for free from Tan's webpage. In
this editor our program looks like this:

The editor recognizes commands automatically and uses different colors (syntax highlighting) to
signal user constants and typing errors in those commands (in black). Storing the code in an .asm file
provides nearly the same text file.

To the top of this page

The assembler
Now we have to translate this code to a machine-oriented form well understood by the AVR chip.
Doing this is called assembling, which means collecting the right command words. If you use
WAVRASM© just click assemble on the menue. The result is shown here:

The assembler reports the complete translation with no errors. If errors occur these are notified.
Assembling resulted in one word of code which resulted from the command we used. Assembling our
single asm-text file now has produced four other files (not all apply here).

The first of these four new files, TEST.EEP, holds the content that should be written to the EEPROM
of the AVR. This is not very interesting in our case, because we didn't program any content for the
EEPROM. The assembler has therefore deleted this file when he completed the assembly run.
The second file, TEST.HEX, is more relevant because this file holds the commands later
programmed into the AVR chip. This file looks like this:

The hex numbers are are written in a special ASCII form, together with adress informations and a
checksum for each line. This form is called Intel-hex-format, and it is very old. The form is well
understood by the programing software.

The third file, TEST.OBJ, will be introduced later, this file is needed to simulate an AVR. Its format
is hexadecimal and defined by ATMEL. Using a hex-editor its content looks like this:

Attention: This file format is not compatible with the programer software, don't use this file to
program the AVR (a very common error when starting).

The fourth file, TEST.LST, is a text file. Display its content with a simple editor. The following
results:

The program with all its adresses, comands and error messages are displayed in a readable form. You
will need that file in some cases to debug errors.

To the top of this page

Programming the chips


To program our hex code to the AVR ATMEL has written the ISP software package. We start the ISP
software and load the hex file that we just generated (applying menue item LOAD PROGRAM). That
looks like this:

Applying menue item PROGRAM will burn our code in the chip's program store. There are a number
of preconditions necessary for this step (the correct parallel port has to be selected, the programming
adapter must be connected, the chip must be on board the adapter, the power supply must be on, etc.).
ATMEL has recently removed the reliable and fast ISP-Software from its webpage. Besides the
ATMEL-ISP and the programming boards other programming boards or adapters could be used,
together with the appropriate programming software. Some of these alternatives are available on the
internet.

To the top of this page

Simulation in the studio


In some cases self-written assembly code, even assembled without errors, does not exactly do what it
should do when burned into the chip. Testing the software on the chip could be complicated, esp. if
you have a minimum hardware and no opportunity to display interim results or debugging signals. In
these cases the studio from ATMEL provides ideal opportunities for debugging. Testing the software
or parts of it is possible, the program could be tested step-by-step displaying results.

The studio is started and looks like this:

First we open a file (menue item FILE OPEN). We demonstrate this using the tutorial file test1.asm,
because there are some more commands and action that in our single-command program above. Open
the file TEST1.OBJ that results by assembling TEST1.asm. You are asked which options you like to
use (if not, you can change these using the menue item SIMULATOR OPTIONS). The following
options will be selected:

In the device selection section we select the desired chip type. The correct frequency should be
selected if you like to simulate correct timings.

In order to view the content of some registers and what the processor's status is we select VIEW
PROCESSOR and REGISTERS. The display should now look like this:

The processor window displays all values like the command counter, the flags and the timing
information (here: 1 MHz clock). The stop watch can be used to measure the necessary time for
going through routines etc.

Now we start the program execution. We use the single step opportunity (TRACE INTO or F11).
Using GO would result in continous exection and not much would be seen due to the high speed of
simulation. After the first executed step the processor window should look like this:

The program counter is at step 1, the cycle counter at 2 (RJMP needed two cycles). At 1 MHz clock
two microseconds have been wasted, the flags and pointer registers are not changed. The source text
window displays a pointer on the next command that will be executed.

Pressing F11 again executes the next command, register mp (=R16) will be set to 0xFF. Now the
register window should highlite this change:

Register R16's new value is displayed in red letters. We can change the value of a register at any time
to test what happens then.

Now step 3 is executed, output to the direction register of Port B. To display this we open a new I/O
view window and select Port B. The display should look like this:

The Data Direction Register in the I/O-view window of Port B now shows the new value. The values
could be changed manually, if desired, pin by pin.

The next two steps are simulated using F11. They are not displayed here. Setting the output ports to
one with the command LDI mp,0xFF and OUT PORTB,mp results in the following picture in the I/O
view:

Now the output port bits are all one, the I/O view shows this.

That is our short trip through the simulator software world. The simulator is capable to much more,
so it should be applied extensively in cases of design errors. Visit the different menue items, there is
much more than showed here.

To the top of this page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/TOOLS.html1/20/2009 7:52:59 PM
Tools for AVR assembly programing

Path: Home => english => Assembler intro => tools

Tools for AVR assembly programing


This page introduces the first steps for programming in assembler using the STK500 board and the
ATMEL-Studio 3 (version 3.52). This version of the studio includes all necessary steps for writing
and programming software for the AVR devices. The following steps are shown:

1. editing a source file,


2. assemble the source file, and
3. the simulator.

The necessary software tools are distributed on ATMEL's webpage. Tools are © ATMEL.Different
versions of the studio might look different to the ones shown here. This is not a handbook, it is just a
short introduction for the start. Installation of the studio software is not shown here. After starting
Studio you should see the following picture:

To the top of this page

The editor
An assembler program is a simple text file. In order to include different informations other than
source informations the studio defines a project. We start with creating a new project. We have to
define a name for the project, its location and the assembler we would like to assemble our source
code with.

This opens a new project view.

By clicking the right button of the mouse while we are over the assembler files section we can select
to create a new source file.

Within the editor window we type in our source code. This one just turns lamps on port B on and off.

Note that the studio recognizes commands (like LDI) only if you type them in small letters (who
invented that?). Labels and defined constants are not recognized, even if defined properly (Tan's
editor is still better than ATMEL's). Also note that the position of the include-files has been changed
in this version.

To the top of this page

Assembling the source files


After typing in we assemble the program. In the project window we click on the right mouse button
ans select assemble. The result is that a new message window opens.

If you get error messages here you have to debug the source code.

The program is ready now for download into the AVR chip, which is not described here further.

To the top of this page

Simulating program execution


If serious bugs have to be found or more complex routines have to be tested you can simulate
program execution.
In that case we select build and run. In the source code a yellow marker points to the next line of code
to be executed next.

The key F11 steps through the source code and executes the next command. In order to see what is
going on in the register section we first open a register view window. The LDI instruction loads hex-
FF to the register R16.

The next command writes to the data direction register of port B. We can open a view window of the
ports to see what is going on. The following is happening when we execute the OUT command to
DDRB.

After execution of the second OUT command (hex-AA to port B) we see the change in the port's data
register.

Studio has a lot more opportunities build in for other purposes that can't be discussed here in detail.
So try out the other ones.

To the top of this page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/STUDIO352.html1/20/2009 7:53:01 PM
http://www.avr-asm-tutorial.net/avr_gra/wavrasm.gif

http://www.avr-asm-tutorial.net/avr_gra/wavrasm.gif1/20/2009 7:53:02 PM
http://www.avr-asm-tutorial.net/avr_gra/eingabe.gif

http://www.avr-asm-tutorial.net/avr_gra/eingabe.gif1/20/2009 7:53:05 PM
http://www.avr-asm-tutorial.net/avr_gra/silliksaar.gif

http://www.avr-asm-tutorial.net/avr_gra/silliksaar.gif1/20/2009 7:53:10 PM
http://www.avr-asm-tutorial.net/avr_gra/assemble.gif

http://www.avr-asm-tutorial.net/avr_gra/assemble.gif1/20/2009 7:53:11 PM
http://www.avr-asm-tutorial.net/avr_gra/hex.gif

http://www.avr-asm-tutorial.net/avr_gra/hex.gif1/20/2009 7:53:14 PM
http://www.avr-asm-tutorial.net/avr_gra/obj.gif

http://www.avr-asm-tutorial.net/avr_gra/obj.gif1/20/2009 7:53:16 PM
http://www.avr-asm-tutorial.net/avr_gra/lst.gif

http://www.avr-asm-tutorial.net/avr_gra/lst.gif1/20/2009 7:53:20 PM
http://www.avr-asm-tutorial.net/avr_gra/isp.gif

http://www.avr-asm-tutorial.net/avr_gra/isp.gif1/20/2009 7:53:22 PM
http://www.avr-asm-tutorial.net/avr_gra/studio.gif

http://www.avr-asm-tutorial.net/avr_gra/studio.gif1/20/2009 7:53:27 PM
http://www.avr-asm-tutorial.net/avr_gra/options.gif

http://www.avr-asm-tutorial.net/avr_gra/options.gif1/20/2009 7:53:29 PM
http://www.avr-asm-tutorial.net/avr_gra/view.gif

http://www.avr-asm-tutorial.net/avr_gra/view.gif1/20/2009 7:53:33 PM
http://www.avr-asm-tutorial.net/avr_gra/step1.gif

http://www.avr-asm-tutorial.net/avr_gra/step1.gif1/20/2009 7:53:35 PM
http://www.avr-asm-tutorial.net/avr_gra/step2.gif

http://www.avr-asm-tutorial.net/avr_gra/step2.gif1/20/2009 7:53:36 PM
http://www.avr-asm-tutorial.net/avr_gra/step3.gif

http://www.avr-asm-tutorial.net/avr_gra/step3.gif1/20/2009 7:53:38 PM
http://www.avr-asm-tutorial.net/avr_gra/step6.gif

http://www.avr-asm-tutorial.net/avr_gra/step6.gif1/20/2009 7:53:40 PM
Tools for programming in assembler language: Studio 4

Path: Home => AVR-english => Beginner => Studio 4

First steps with Studio 4


This page introduces you to edit, simulate and program an AVR in assembler using ATMEL-Studio 4
free software. This software is available for download on ATMEL's homepage. The screenshots
provided here are © ATMEL. Please note that the screenshots might be different from those of other
versions of Studio.
This introduction is not a handbook on Studio 4, it just demonstrates some basic ideas on how to use
the software to do the first steps. Installation of the software also is not included.

To the top of that page

To start a new project


After starting studio 4 a new project will be created, like the screen in the following picture.

Following the selection of a project name and selecting a folder to store the project files in, we will
be forced to select an AVR type.

The built-in editor opens a text file, in which we type in the assembler source code.

That's it with the editor.

To the top of that page

Simulation is a matter of the point of view


To test this program in the simulator, we select Build-and-run from the studio menue. In the lower
window, called output window, the output of the assembler is shown (hopefully, without any error
messages). A yellow arrow points on the next instruction to be simulated. To see what is going on,
we close the output window, and open up a register view for the registers R16..R31 in the left
window.

By using the view menue, we can open up additional views, e.g. a view on the content of all registers.
By pressing F11 we step through the program, instruction by instruction. After two steps in that
program the register window looks like this.

After execution of the EOR instruction the register content of R17 has changed, the colour changes to
red.

The flags of the status register SREG can be viewed in the left window by selecting I/O, CPU and
SREG.

The same window shows the content of the ports, here: Port B.

To the top of that page

Programing the AVR


In order to transfer the program to the AVR, the Studio provides an interface to the programmer
board STK500 (and to some other boards). This is selected in the menue Tools. The studio then
communicates with the STK500 board.

With that interface, either the currently edited, assembled and simulatede program or an external .hex
file can be transferred to the AVR.

If you have other programming equipment, you can use the .hex- and .eep-files generated by the
studio to feed them to the AVR with your own transfer routines.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/STUDIO4.html1/20/2009 7:53:42 PM
Structure of assembler programs

Path: Home => AVR-english => Beginner => Structure

Structure of AVR-assembler-programs
This page shows the basic structure of an assembler program. These structures are typical for
AT90Sxxxx assembler. This text discusses comments, header informations, code at program start and
the general structure of programs.

Comments
The most helpful things in assembler programs are comments. If you need to understand older code
that you wrote, sometimes years after, you will be happy about having some or more hints what is
going on in that line. If you like to keep your ideas secret, and to hide them aginst yourself and
others: don't use comments.

A comment starts with a semicolon. All that follows behind on the same line will be ignored by the
compiler. If you need to write a comment over multiple lines, start each line with a semicolon. So
each assembler program should start like that:

;
; Click.asm, Program to switch a relais on and off each two seconds
; Written by G.Schmidt, last change: 7.10.2001
;

Put comments around all parts of the program, be it a complete subroutine or a table. Within the
comment mention the special nature of the routine, pre-conditions necessary to call or run the routine.
Also mention the results of the subroutine in case you later will have to find errors or extend the
routine later.

Single line comments are defined by adding a semicolon behind the command on the line. Like this:

LDI R16,0x0A ; Here something is loaded


MOV R17,R16 ; and copied somewhere else

To the top of that page

Things to be written on top


Purpose and function of the program, the author, version information and other comments on top of
the program should be followed by the processor type that the program is written for, and by relevant
constants and by a list with the register names.

The processor type is especially important. Programs do not run on other chip types without changes.
The commands are not completely understood by all types, each type has typical amounts of
EEPROM and internal SRAM. All these special features are included in a header file that is named
xxxxdef.inc, with xxxx being the chip type, e.g. 2313, 2323, or 8515. These files are available by
ATMEL. It is good style to include this file at the beginning of each program. This is done like that:

.NOLIST ; Don't list the following in the list file


.INCLUDE "C:\avrtools\appnotes\8515def.inc" ; Import of the file
.LIST ; Switch list on again

The path, where this file can be found, is only necessary if you didn't copy that file to the folder
where your assembler program is located. Of course you have to change this path to fit to your place
where these files are located.

During assembling listing of the results is switched on by default. This might result in very long list
files (*.lst) if you include the header file. NOLIST turns off this listing for a while, LIST turns it on
again.

Let's have a short look at the header file. First these files define the processor type:

.DEVICE AT90S8515 ; The target device type

This results in error messages, if you use code sequences that are not defined for this type of
processor. You don't need to define this within your program as this is already defined within the
header file.

The header file defines the registers XH, XL, YH, YL, ZH and ZL. These are needed if you use the
16-bit-pointers X, Y or Z to access the higher or lower byte of the pointer separately. The port's
locations are also defined in the header file, so PORTB translates to hex 18. The port's names are
defined with the same names that are used in the data sheets for the respective processor type. This
also applies to single bits in the ports. Read access to port B, bit 3, can be done using its bit name
PINB3, as defined in the data sheet.

In other words: if you forget to include the header file you will run into a lot of error messages during
assembly. The resulting error messages are in many cases not very much related to the missing
header file. This is due to a serious bug (or is it a MS-style-feature?) in ATMEL's assemblers: a
missing label or constant is not reported as such, but it is assumed to be zero. You can easily imagine
that the resulting code does strange things with your AVR in action.

Others things that should be on top of your programs are the register definitions you work with, e.g.:

.DEF mpr = R16 ; Define a new name for register R16

This has the advantage of having a complete list of registers, and to see which registers are still
available and unused. Renaming registers avoids conflicts in the use of these registers and the names
are easier to remember.

Furtheron we define the constants on top of the source file, especially those that have a relevant role
in different parts of the program. Such a constant would, e.g., be the Xtal frequency that the program
is adjusted for, if you use the serial interface on board. With

.EQU fq = 4000000 ; XTal frequency definition

at the beginning of the source code you immediately see for which clock you wrote the program.
Very much easier than searching for this information within 1482 lines of source code.

To the top of that page

Things that should be done at program start


After you have done the header, the program code should start. At the beginning of the code the
reset- and interrupt-vectors (their function see in the JUMP section) are placed. As these require
relative jumps, we should place the respective interrupt service routines right behind. There is some
space left then for other subroutines, before we place the main program.

The main program always starts with setting registers to default values, initialisation of the stack
pointer and of the hardware components used. The following code is specfic for the program.

To the top of that page

Structuring of program code


The described standardized structure is included in a standard form for the 8515 that is also included
in the source code section. Used it to start with your own 8515 programs, or to create similiar forms
for other types.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/STRUCTURE.html1/20/2009 7:53:44 PM
Standard sheet for 8515 assembler

Path: Home => Language select => AVR-main => beginners => Standard 8515 file

Standard 8515 programming file structure


; ***************************************************************
; * *
; * *
; * *
; * *
; * *
; * (C)2002 by Last change: *
; ***************************************************************
;
; Hardware requirements:
;
; Software features:
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Constants
;
.EQU xyz = 12345
;
; Used registers
;
.DEF mpr = R16
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-vectors
;
rjmp Start ; Reset-vector
rjmp IInt0 ; External Interrupt Request 0
rjmp IInt1 ; External Interrupt Request 1
rjmp TCpt1 ; Timer/Counter1 Capture event
rjmp TCmpA ; Timer/Counter1 Compare match A
rjmp TCmpB ; Timer/Counter1 Compare match B
rjmp TOvf1 ; Timer/Counter1 Overflow
rjmp TOvf0 ; Timer/Counter0 Overflow
rjmp URxAv ; Uart Rx char available
rjmp UTxDe ; Uart Tx data register empty
rjmp UTxCp ; Uart Tx complete
rjmp AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0
;
IInt0:
reti
;
; External Interrupt 1
;
IInt1:
reti
;
; Timer/Counter 1, Capture event
;
TCpt1:
reti
;
; Timer/Counter 1, Compare match interrupt A
;
TCmpA:
reti
;
; Timer/Counter 1, Compare match interrupt B
;
TCmpB:
reti
;
; Timer/Counter 1, Overflow interrupt
;
TOvf1:
reti
;
; Timer/Counter 0, Overflow interrupt
;
TOvf0:
reti
;
; SPI Serial Transfer Complete interrupt
;
SIStc:
reti
;
; Uart Rx Complete Interrupt
;
URxAv:
reti
;
; Uart Data register empty interrupt
;
UTxDe:
reti
;
; Uart Tx complete interrupt
;
UTxCp:
reti
;
; Analog comparator interrupt
;
AnaCp:
reti
;
; **************** End of interrupt service routines ***********
;
; Various subroutines
;
; **************** End of the subroutine section ***************
;
; ******************** Main program ****************************
;
; Main program routine starts here
;
Start:
rjmp start

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/8515STD.html1/20/2009 7:53:45 PM
Directives and expressions in AVR-Assembler language

Pfad: Home => AVR-Overview => Programming techniques => Directives/Expressions

Programming techniques in AVR Assembler


language
Assembler-Directives
Assembler-Directives control the assembler, they don't create any own code. The leading dot must be
in column 1 of the line.
Segment Directive Description
Defines the type of the target processor and the applicable set of
.DEVICE instructions (illegal instructions for that type trigger an error message,
syntax: .DEVICE AT90S8515)
.DEF Defines a synonym for a register (e.g. .DEF MyReg = R16)
Defines a symbol and sets its value (later changes of this value remain
Header .EQU possible, syntax: .EQU test = 1234567, internal storage of the value is
4-byte- Integer)
.SET Fixes the value of a symbole (later redefinition is not possible)
Includes a file and assembles its content, just like its content would be
.INCLUDE part of the calling file (typical e.g. including the header file: .
INCLUDE "C:\avrtools\appnotes\8515def.inc")
Start of the code segment (all that follows is assembled to the code
.CSEG
segment and will go to the program space)
Inserts one or more constant bytes in the code segment (could be
numbers from 0..255, an ASCII-character like 'c', a string like 'abcde'
.DB or a combination like 1,2,3,'abc'. The number of inserted bytes must
be even, otherwise an additional zero byte will be inserted by the
assembler.)
Code Insert a binary word in the code segment (e.g. produces a table within
.DW
the code)
Macros will be listed in the .LST-file. (Default is that macros are not
.LISTMAC
listed)
Beginning of a macro (no code will be produced, call of the macro
.MACRO later produces code, syntax: .MACRO macroname parameters, calling
by: macroname parameters)
.ENDMACRO End of the macro
Assemble to the EEPROM-segment (the code produced will go to the
.ESEG
EEPROM section, the code produces an .EEP-file)
Inserts one or more constant bytes in the EEPROM segment (could be
EEPROM .DB numbers from 0..255, an ASCII-character like 'c', a string like 'abcde'
or a combination like 1,2,3,'abc'.)
Inserts a binary word to the EEPROM segment (the lower byte goes to
.DW
the next adress, the higher byte follows on the incremented address)
Assemble to the data segment (here only BYTE directives and labels
.DSEG
are valid, during assembly only the labels are used)
SRAM
Reserves one or more bytes space in the data segment (only used to
.BYTE
produce correct labels, does not insert any values!)
Defines the address within the respective segment, where the
.ORG
assembler assembles to (e.g. .ORG 0x0000)
Switches the listing to the .LST-file on (the assembled code will be
.LIST
listet in a readable text file .LST)
Everywhere .NOLIST Switches the output to the .LST-file off, suppresses listing.
Inserts the content of another source code file, as if its content would
.INCLUDE be part of the source file (typical e.g. including the header file: .
INCLUDE "C:\avrtools\appnotes\8515def.inc")
.EXIT End of the assembler-source code (stops the assembling process)

Advanced Assembler Directives


Advanced Assembler Directives allow

● conditional assembly: a code sequence is translated only if a certain condition is met or not,
otherwise another code sequence is generated,
● output of messages or forced error conditions: these allow signalisation of certain conditions
during assembly or force exiting the assembly process on a certain condition.

Please note again, that these directives are only meaningful for the assembler and during the
assembly process, the assembled program itself, as loaded into the AVR, does not have any
conditions!

Not all of the assemblers understand these directives. Newer versions from ATMEL, the latest
version of the Studio and my own assembler gavrasm know these directives well.

The Syntax of these directives look like this:

● .IF <Condition>, then code lines, then .ENDIF. Condition is an expression which is either
true or false, e.g. a comparision like a<b, a>b or a==b.
● .IF <Condition>, then code lines, then .ELSE, then code lines, then .ENDIF. If the condition
is met (true), then the first series of code lines is translated, if not the second code sequence
behind ELSE is translated.
● .IF <Condition 1>, then code lines, then .ELIF <Condition 2>, then code lines, then .
ENDIF. If condition 1 is true, the first code sequence is generated, if not the condition 2 will
be checked. If this is true, then the second code sequence is generated. If neither condition 1
nor condition 2 are true, no code will be generated.
● .IFDEF <Symbol>. Checks if a symbol has been defined. If so, the code is translated and
inserted. If not, the following code sequence is not translated. Can be combined with the
ELSE and ELIF directive, and must be finished by a ENDIF directive.
● .IFNDEF <Symbol>. Produces the opposite: if the symbol is not defined, the code is
translated.
● .MESSAGE "<text>". Outputs the message text during assembling. Can be used in
combination with conditional assembly to signal the result of the comparision or output any
other comments.
● .ERROR "<text>". Outputs the message text and causes an error condition. Can be used to
skip further assembling, if a certain value exceeds a certain limit or is too small.

Assembler expressions
Expressions are needed to calculate within the assembler source code. These expressions are
calculated during the assembly process, they don't produce any execuatble code.
Type Symbol Description
+ Addition
- Subtraction or negative number
Calculation
* Multiplication
/ Integer-Division
& Bitwise AND
| Bitwise OR
^ Bitwise Exclusive-OR
Binary
~ Bitwise NOT
<< Shift left
>> Shift right
< Less than
> Greater than
== Equal
<= Less or equal
Logical >= Graeter or equal
!= Unequal
&& AND
|| OR
! NOT

Shift left
Some hints for Shift-Left (<<): the following code lines are used very often:

ldi r16,1<<ADSC
out ADCSRA,r16

In this example, ADSC is a certain bit in Port ADCSRA, both defined somewhere in the header file
for this AVR. In that case it starts an AD conversion (in most cases bit 6), if written to the Port
ADCSRA. The expression with << causes that a One (binary 0000.0001) is shifted left six times and
gets to 0100.0000. This number is written to the port ADCSRA and causes an AD conversion start.

Using this notation has the advantage, that the exact location of the ADSC bit in the ADCSRA port
doesn't have to be known exactly. Its location can even change from one header file to another,
without changing the source code. Compared to the formulation

ldi r16,0b01000000
out 0x06,r16

the transparency is much higher. And not having to count binary zeroes is another advantage.

What if other bits in the same port have to be set to one simultanously, for example the Interrupt
Enable bit ADIE (bit 3)? Then just OR these bitwise:

ldi r16,(1<<ADSC) | (1<<ADIE)


out ADCSRA,r16

The brackets set the exact calculation priorities.

To the top of that page

©2002-2005 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/beginner/DIREXP.html1/20/2009 7:53:47 PM
Binary calculations in AVR Assembler

Path: Home => AVR-Overview => Binary calculations

Binary calculations in AVR


Assembler

This page demonstrates calculations with binary numbers in AVR assembler. With simple examples
multiplication and division of 8-bit binary numbers as well as conversions in the number format are
shown.

1. Multiplication of two 8-bit-binaries


❍ Decimal multiplication

❍ Binary multiplication

❍ AVR Assembler multiplication

❍ Rotate instructions

❍ Multplication in the Simulator

2. Division of a 16-bit-binary by a 8-bit-binary


❍ Decimal division

❍ Binary division

❍ Division steps

❍ Simulation of division

3. Conversion of number formats


❍ Basics on number formats

❍ General rules of the assembler routines

❍ ASCII to binary conversion

❍ BCD to binary conversion

❍ Binary multplication by 10

❍ Binary to ASCII conversion

❍ Binary to BCD conversion

❍ Binary to hex conversion

❍ Hex to binary conversion

4. Conversions to fixed decimal numbers


❍ Sense and Nonsense of floating point numbers

❍ Linear conversions

❍ Example 1: 8-Bit-AD-Copnverter to 0.00 to 5.00 Volt

❍ Example 2: 10-Bit-AD-Converter to 0.000 to 5.000 Volt

5. Hardware multiplication
❍ Hardware multiplication of 8-by-8-bit binaries

❍ Hardware multiplication of 16-by-8-bit binaries

❍ Hardware multiplication of 16-by-16-bit binaries

❍ Hardware multiplication of 16-by-24-bit binaries

To the top of that page

©2002-2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/index.html1/20/2009 7:53:48 PM
Binary multiplication in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Multiplication

Binary multiplication in AVR


Assembler

Decimal multiplication
In order to multiply two 8-bit-binaries we remind ourselves, how this is done with decimal numbers:

1234 * 567 = ?
------------------------
1234 * 7 = 8638
+ 12340 * 6 = 74040
+ 123400 * 5 = 617000
------------------------
1234 * 567 = 699678
========================

In single steps decimal:

1. We multiply the first number by the lowest significant digit of the second number and add this
to the result.
2. We multiply the first number by 10 and then by the next higher digit of the second number
and add to the result.
3. We multiply the first number by 100, then with the third-highest digit, and add this to the
result.

Binary multiplication
Now in binary. Multiplication with the single digits is not necessary, because there are only the digits
1 (add the number) and 0 (don't add the number). Multiplication by 10 in decimal goes to
multiplication by 2 in binary mode. Multiplication by 2 is done easily, either by adding the number
with itself, or by shifting all bits one position left and writing a 0 to the void position on the right.
You see that binary math is very much easier than decimal. Why didn't mankind use this from the
beginning?

AVR-Assembler program
The program for multiplication in AVR assembler language is demonstrated in HTML following this
link, the source code is available at this link. This source code can be assembled, the resulting object-
file can be opened in the simulator studio provided as free software by ATMEL. These are the
positions and registers used in the program:

. rmh = R1 = 0x00 rm1 = R0 = 0xAA


Z1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0
* . rm2 = R2 = 0x55
Z2 0 1 0 1 0 1 0 1
= reh = R4 = 0x00 rel = R3 = 0x00
Erg 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Binary rotation
For understanding the multiplication operation, it is necessary to understand the binary rotation
commands ROL and ROR. These instructions shift all bits of a register one position left (ROL) resp.
right (ROR). The void position in the register is filled with the content of the carry bit of the status
register, the bit that rolls out of the register is shifted to the carry bit. This operation is demonstrated
using 0xAA as an example for ROL and 0x55 as an example for ROR:

Multiplication in the studio


The following screenshots show the multiplication program in the simulator.

1. MULT8E1.gif: The object-code has been opened, the cursor is placed on the first executable
instruction. F11 does single steps.
2. MULT8E2.gif: The registers R0 and R2 are set to 0xAA and 0x55, our test binaries, to be
multiplied.
3. MULT8E3.gif: R2 is rotated to the right, to roll the least significant bit into the carry bit. 0x55
(0101.0101) yielded 0x2A (0010.1010).
4. MULT8E4.gif: Because the carry bit had a one the content of the registers R1:R0 is added to
the (empty) register pair R4:R3, resulting in 0x00AA there.
5. MULT8E5.gif: Now the register pair R1:R0 is rotated one position left to multiply this binary
by 2. From 0x00AA, multiplication by 2 yields 0x0154.
6. The whole multiplication loop is repeated as long there is at least one binary 1 in register R2.
These following loops are not shown here.
7. MULT8E6.gif: Using key F5 of the studio we multi-stepped over these loops to a breakpoint
at the end of the multiplication routine. The result register pair R4:R3 has the result of the
multiplication of 0xAA by 0x55: 0x3872.

This wasn't that complicated, just remind yourself on the similiar decimal operations. Binary
multiplication is much easier than decimal.

To the top of that page

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/MULTIPLICATION.html1/20/2009 7:53:50 PM
Multiplication of two 8-bit-binaries

Path: Home => AVR-Overview => Binary calculations => multiplication

; Mult8.asm multiplies two 8-bit-numbers


; to yield a 16-bit-result
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Flow of multiplication
;
; 1.The binary to be multiplicated with, is shifted bitwise
; into the carry bit. If it is a one, the binary number
; is added to the result, if it is not a one that was
; shifted out, the number is not added
; 2.The binary number is multiplied by 2 by rotating it
; one position left, shifting a 0 into the void position.
; 3.If the binary to be multiplied with, is not zero, the
; multiplication loop is repeated. If it is zero, the
; multiplication is done.
;
; Used registers
;
.DEF rm1 = R0 ; Binary number to be multiplicated (8 Bit)
.DEF rmh = R1 ; Interim storage
.DEF rm2 = R2 ; Binary number to be multiplicated with (8 Bit)
.DEF rel = R3 ; Result, LSB (16 Bit)
.DEF reh = R4 ; Result, MSB
.DEF rmp = R16 ; Multi purpose register for loading
;
.CSEG
.ORG 0000
;
rjmp START
;
START:
ldi rmp,0xAA ; example binary 1010.1010
mov rm1,rmp ; to the first binary register
ldi rmp,0x55 ; example binary 0101.0101
mov rm2,rmp ; to the second binary register
;
; Here we start with the multiplication of the two binaries
; in rm1 und rm2, the result will go to reh:rel (16 Bit)
;
MULT8:
;
; Clear start values
clr rmh ; clear interim storage
clr rel ; clear result registers
clr reh
;
; Here we start with the multiplication loop
;
MULT8a:
;
; Step 1: Rotate lowest bit of binary number 2 to the carry
; flag (divide by 2, rotate a zero into bit 7)
;
clc ; clear carry bit
ror rm2 ; bit 0 to carry, bit 1 to 7 one position to
; the right, carry bit to bit 7
;
; Step 2: Branch depending if a 0 or 1 has been rotated to
; the carry bit
;
brcc MULT8b ; jump over adding, if carry has a 0
;
; Step 3: Add 16 bits in rmh:rml to the result, with overflow
; from LSB to MSB
;
add rel,rm1 ; add LSB of rm1 to the result
adc reh,rmh ; add carry and MSB of rm1
;
MULT8b:
;
; Step 4: Multiply rmh:rm1 by 2 (16 bits, shift left)
;
clc ; clear carry bit
rol rm1 ; rotate LSB left (multiply by 2)
rol rmh ; rotate carry into MSB and MSB one left
;
; Step 5: Check if there are still one's in binary 2, if
; yes, go on multiplicating
;
tst rm2 ; all bits zero?
brne MULT8a ; if not, go on in the loop
;
; End of the multiplication, result in reh:rel
;
; Endless loop
;
LOOP:
rjmp loop

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E.html1/20/2009 7:53:51 PM
http://www.avr-asm-tutorial.net/avr_en/source/MULT8E.asm

; Mult8.asm multiplies two 8-bit-numbers


; to yield a 16-bit-result
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Flow of multiplication
;
; 1.The binary to be multiplicated with, is shifted bitwise
; into the carry bit. If it is a one, the binary number
; is added to the result, if it is not a one that was
; shifted out, the number is not added
; 2.The binary number is multiplied by 2 by rotating it
; one position left, shifting a 0 into the void position.
; 3.If the binary to be multiplied with, is not zero, the
; multiplication loop is repeated. If it is zero, the
; multiplication is done.
;
; Used registers
;
.DEF rm1 = R0 ; Binary number to be multiplicated (8 Bit)
.DEF rmh = R1 ; Interim storage
.DEF rm2 = R2 ; Binary number to be multiplicated with (8 Bit)
.DEF rel = R3 ; Result, LSB (16 Bit)
.DEF reh = R4 ; Result, MSB
.DEF rmp = R16 ; Multi purpose register for loading
;
.CSEG
.ORG 0000
;
rjmp START
;
START:
ldi rmp,0xAA ; example binary 1010.1010
mov rm1,rmp ; to the first binary register
ldi rmp,0x55 ; example binary 0101.0101
mov rm2,rmp ; to the second binary register
;
; Here we start with the multiplication of the two binaries
; in rm1 und rm2, the result will go to reh:rel (16 Bit)
;
MULT8:
;
; Clear start values
clr rmh ; clear interim storage
clr rel ; clear result registers
clr reh
;
; Here we start with the multiplication loop
;
MULT8a:
;
; Step 1: Rotate lowest bit of binary number 2 to the carry
; flag (divide by 2, rotate a zero into bit 7)
;
clc ; clear carry bit
ror rm2 ; bit 0 to carry, bit 1 to 7 one position to
; the right, carry bit to bit 7
;
; Step 2: Branch depending if a 0 or 1 has been rotated to
; the carry bit
;
brcc MULT8b ; jump over adding, if carry has a 0
;
; Step 3: Add 16 bits in rmh:rml to the result, with overflow
; from LSB to MSB
;
add rel,rm1 ; add LSB of rm1 to the result
adc reh,rmh ; add carry and MSB of rm1
;
MULT8b:
;
; Step 4: Multiply rmh:rm1 by 2 (16 bits, shift left)
;
clc ; clear carry bit
rol rm1 ; rotate LSB left (multiply by 2)
rol rmh ; rotate carry into MSB and MSB one left
;
; Step 5: Check if there are still one's in binary 2, if
; yes, go on multiplicating
;
tst rm2 ; all bits zero?
brne MULT8a ; if not, go on in the loop
;
; End of the multiplication, result in reh:rel
;
; Endless loop
;
LOOP:
rjmp loop

http://www.avr-asm-tutorial.net/avr_en/source/MULT8E.asm1/20/2009 7:53:53 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E1.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E1.gif1/20/2009 7:53:55 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E2.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E2.gif1/20/2009 7:53:58 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E3.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E3.gif1/20/2009 7:54:01 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E4.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E4.gif1/20/2009 7:54:04 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E5.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E5.gif1/20/2009 7:54:07 PM
http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E6.gif

http://www.avr-asm-tutorial.net/avr_en/calc/MULT8E6.gif1/20/2009 7:54:10 PM
Binary division in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Division

Binary division in AVR Assembler

Decimal division
Again we start with the decimal division, to better understand the binary division. We assume a
division of 5678 by 12. This is done like this:

5678 : 12 = ?
--------------------------
- 4 * 1200 = 4800
----
878
- 7 * 120 = 840
---
38
- 3 * 12 = 36
--
2
Result: 5678 : 12 = 473 Remainder 2
===================================

Binary division
In binary the multiplication of the second number (4 * 1200, etc.) is not necessary, due to the fact that
we have only 0 and 1 as digits. Unfortunately binary numbers have much more single digits than their
decimal equivalent, so transferring the decimal division to its binary equivalent is a little bit
inconvenient. So the program works a bit different than that.

The division of a 16-bit binary number by a 8-bit binary in AVR assembler is listed in HTML format
following this link. The source code is at this link.

Program steps during division


During execution of the program the following steps are ran:

1. Definition and preset of the registers with the test binaries,


2. presetting the interim register and the result register pair (the result registers are presetted to
0x0001! After 16 rotations the rolling out of the one stops further division steps.),
3. the 16-bit-binary in rd1h:rd1l is rotated bitwise to the interim register rd1u (multiplication by
2), if a 1 is rotated out of rd1u, the program branches to the subtraction step in step 4
immediately,
4. the content of the interim register is compared with the 8-bit binarly in rd2, if rd2 is smaller it
is subtracted from the interim register and the carry-bit is set to one, if rd2 is greater the
subtraction is skipped and a zero is set to the carry flag,
5. the content of the carry flag is rotated into the result register reh:rel from the right,
6. if a zero rotated out of the result register, we have to repeat the division loop, if it was a one
the division is completed.

If you don't understand rotation yet you'll find this operation discussed in the multiplication section.

Division in the simulator


The following screen shots demonstrate the program steps in the studio. To do this, you have to
assemble the source code and open the resulting object file in the studio.

1. DIV8E1.gif: The object code has been started, the cursor is on the first executable instruction.
The key F11 performs single steps.
2. DIV8E2.gif: The test binaries 0xAAAA and 0x55, to be divided, are written to the registers
R1:R0 and R3.
3. DIV8E3.gif: The interim register R2 and the result register pair are set to their predfined
values.
4. DIV8E4.gif: R1:R0 was rotated left to R2, from 0xAAAA the doubled value of 0x015554 was
yielded.
5. DIV8E5.gif: No overflow from rotation into carry has occurred and 0x01 in R2 was smaller
than 0x55 in R3, so subtraction was skipped. A zero in the carry is rotated into the result
register R5:R4. The former content of the result register, a single 1-bit in position 0 has rotated
to position 1 (content now: 0x0002). As a zero was rotated out of the result register pair, the
next step to be executed is a branch to the beginning of the division loop start and the loop is
repeated.
6. DIV8E6.gif: After executing the loop 16 times we have reached the breakpoint set at the end
of the division routine. The result register in R5:R4 holds 0x0202, the result of the division.
The registers R2:R1:R0 are empty, so we do not have a remainder left. If a remainder would
have been resulted we can use it to decide whether an incrementation of the result should take
place, rounding of the result up. This step is not coded here.
7. DIV8E7.gif: The whole division needs 60 micro-seconds processor time (open a processor
view in the studio menue). A rather long time for a division.

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/DIVISION.html1/20/2009 7:54:12 PM
Division of a 16-bit-binary by a 8-bit-binary

Path: Home => AVR-Overview => Binary Calculations => Division

; Div8 divides a 16-bit-number by a 8-bit-number


; Test: 16-bit-number: 0xAAAA, 8-bit-number: 0x55
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers
;
.DEF rd1l = R0 ; LSB 16-bit-number to be divided
.DEF rd1h = R1 ; MSB 16-bit-number to be divided
.DEF rd1u = R2 ; interim register
.DEF rd2 = R3 ; 8-bit-number to divide with
.DEF rel = R4 ; LSB result
.DEF reh = R5 ; MSB result
.DEF rmp = R16; multipurpose register for loading
;
.CSEG
.ORG 0
;
rjmp start
;
start:
;
; Load the test numbers to the appropriate registers
;
ldi rmp,0xAA ; 0xAAAA to be divided
mov rd1h,rmp
mov rd1l,rmp
ldi rmp,0x55 ; 0x55 to be divided with
mov rd2,rmp
;
; Divide rd1h:rd1l by rd2
;
div8:
clr rd1u ; clear interim register
clr reh ; clear result (the result registers
clr rel ; are also used to count to 16 for the
inc rel ; division steps, is set to 1 at start)
;
; Here the division loop starts
;
div8a:
clc ; clear carry-bit
rol rd1l ; rotate the next-upper bit of the number
rol rd1h ; to the interim register (multiply by 2)
rol rd1u
brcs div8b ; a one has rolled left, so subtract
cp rd1u,rd2 ; Division result 1 or 0?
brcs div8c ; jump over subtraction, if smaller
div8b:
sub rd1u,rd2; subtract number to divide with
sec ; set carry-bit, result is a 1
rjmp div8d ; jump to shift of the result bit
div8c:
clc ; clear carry-bit, resulting bit is a 0
div8d:
rol rel ; rotate carry-bit into result registers
rol reh
brcc div8a ; as long as zero rotate out of the result
; registers: go on with the division loop
; End of the division reached
stop:
rjmp stop ; endless loop

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E.html1/20/2009 7:54:13 PM
http://www.avr-asm-tutorial.net/avr_en/source/DIV8E.asm

; Div8 divides a 16-bit-number by a 8-bit-number


; Test: 16-bit-number: 0xAAAA, 8-bit-number: 0x55
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers
;
.DEF rd1l = R0 ; LSB 16-bit-number to be divided
.DEF rd1h = R1 ; MSB 16-bit-number to be divided
.DEF rd1u = R2 ; interim register
.DEF rd2 = R3 ; 8-bit-number to divide with
.DEF rel = R4 ; LSB result
.DEF reh = R5 ; MSB result
.DEF rmp = R16; multipurpose register for loading
;
.CSEG
.ORG 0
;
rjmp start
;
start:
;
; Load the test numbers to the appropriate registers
;
ldi rmp,0xAA ; 0xAAAA to be divided
mov rd1h,rmp
mov rd1l,rmp
ldi rmp,0x55 ; 0x55 to be divided with
mov rd2,rmp
;
; Divide rd1h:rd1l by rd2
;
div8:
clr rd1u ; clear interim register
clr reh ; clear result (the result registers
clr rel ; are also used to count to 16 for the
inc rel ; division steps, is set to 1 at start)
;
; Here the division loop starts
;
div8a:
clc ; clear carry-bit
rol rd1l ; rotate the next-upper bit of the number
rol rd1h ; to the interim register (multiply by 2)
rol rd1u
brcs div8b ; a one has rolled left, so subtract
cp rd1u,rd2 ; Division result 1 or 0?
brcs div8c ; jump over subtraction, if smaller
div8b:
sub rd1u,rd2; subtract number to divide with
sec ; set carry-bit, result is a 1
rjmp div8d ; jump to shift of the result bit
div8c:
clc ; clear carry-bit, resulting bit is a 0
div8d:
rol rel ; rotate carry-bit into result registers
rol reh
brcc div8a ; as long as zero rotate out of the result
; registers: go on with the division loop
; End of the division reached
stop:
rjmp stop ; endless loop

http://www.avr-asm-tutorial.net/avr_en/source/DIV8E.asm1/20/2009 7:54:14 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E1.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E1.gif1/20/2009 7:54:18 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E2.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E2.gif1/20/2009 7:54:22 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E3.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E3.gif1/20/2009 7:54:25 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E4.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E4.gif1/20/2009 7:54:28 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E5.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E5.gif1/20/2009 7:54:31 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E6.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E6.gif1/20/2009 7:54:34 PM
http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E7.gif

http://www.avr-asm-tutorial.net/avr_en/calc/DIV8E7.gif1/20/2009 7:54:37 PM
Number format conversion in AVR Assembler

Path: Home => AVR-overview => Binary calculations => Conversions

Number format conversion AVR-


Assembler

Converting numbers is very often used in assembler, because processors prefer calculating in binary,
while people on a terminal prefer decimal numbers. If one has to communicate from within an
assembler routine with one of the human species, number conversion is a must. This page provides
some basic know how on number conversion. Learn a bit more in detail, how conversion between
different number systems is done.

For those who prefer going directly to the source code, here is the link to the HTML version and the
link to the asm version of the source code.

Number format basics


The number systems discussed here ar:

● Decimal: Each byte represents a decimal digit, coded in ASCII. Decimal 49 or binary $30
represents the digit 0, decimal 49 the digit 1, and so on to 57, which represents a 9. Other
numbers, from 0 to 47 and from 58 to 255, do not represent correct digits. (Why 0 is 48, and
not 0, can only be understood historically, it reaches back to the times of US military teletype
machines, but this is another long story).
● BCD-numbers: BCD means Binary Coded Decimal. It's like decimal ASCII, but the decimal
digit zero here is indeed 0. BCDs reach from 0 to 9. Numbers greater than 9 (that is 10 to 255)
are illegal and not BCD.
● Binary numbers: Here only the digits 0 and 1 are used. Read from the least significant bit,
the value of the digits doubles, so the binary 1011 is equal 1*(2 ** 0) + 1*(2 ** 1) + 0*
(2 ** 2) + 1*(2 ** 3). Just like decimal 1234 is equal to 4*(10 ** 0) + 3*(10 ** 1) + 2*
(10 ** 2) + 1*(10 ** 3). (By the way: each number ** 0 is 1, except 0 ** 0, which is not
known exactly). Binary numbers are handled in packages of 4 (called nibble), 8 (called Byte)
or 16 (called word), because single bits are very small numbers and e.g. do not allow to buy
five apples (needs a package of three bits).
● Hex numbers: Hex numbers are packages of four single bits. These four bits represent 16
different hex digits. The first ten are named like their decimal relatives, but the digits 10 to 15
are named A to F. As string of ASCII-coded hex digits this is rather unlucky, because the
ASCII representation of the 9 is 57, of the A is 65. If you prefer using a..f for the additional
six digits in hex, the ASCII representation is even 97. This is relevant for number conversions,
because these hex digits are distributed over the ASCII character table, complicating
conversion.

So far the number format basics.

General rules of the assembler routines


The AVR assembler software for conversion has to be somehow flexible to apply in different
situations. So it is better to spent some thinking before writing it. I have adopted some rules in
writing this source code. Here are the rules:

● Binary numbers: All binaries are designed for 16 Bit, with values between 0 and 65,535.
They are generally located in the register pair rBin1H (upper 8 bits, MSB) and rBin1L (lower
8 bits, LSB). This binary word is abbreviated as rBin1H:L. Preferred location for this word are
the registers R2 and R1, but it doesn't really matter, where and in which order you place it.
Some conversions require a second register pair, named rBin2H:L. You can place it in the
registers R4 and R3. Generally the values in this register pair are restored after use, so you can
use it for other purposes, too, without the risk of a conflict.
● BCD- and ASCII-coded numbers: These numbers are most often located somewhere in the
SRAM space of the AVR, e.g. in a buffer of incoming characters from the SIO. So these
numbers are generally handled with the pointer register Z (pointer register ZH:ZL or R31:
R30). The numbers are assumed to be in the following order: The higher the value of the digit
the lower the pointer adress. The number 12345 so would be located in SRAM like this:
$0060: 1, $0061: 2, $0062: 3, and so on. You can also place the pointer Z to locations in the
register space, e.g. to $0005. The 12345 would then be located like this: R5: 1, R6: 2, and so
on. The conversion software so works as well in the register space, if you place the digits in
that order to the registers. No need to write a special conversion routine for the register space.
But beware of pointer bugs: the software overwrites registers without asking you. You can
even overwrite the pointer registers ZH:ZL. What happens then is rather unknown. Thorough
planning of the register space is a must, if you use that routines in register space.
● Packaging: Because not all conversion routines are necessary, I have packed the routines into
four packages. The last two packages are only dedicated to hex conversions. The first package
converts ASCII- and BCD-numbers to binaries, package II converts binaries to ASCII and
BCD. Each package with the called subroutines in it runs separately. If you remove parts of
the package content, be sure to keep the appropriated subroutines. The whole four packages
compile to 217 words of program space.
● Errors: If a number conversion leads to an error, the T-flag is set to one. The T-flag can be
used to react to an error, e.g. by using the branch instructions BRTS and BRTC. If you need
the T-flag for other purposes, feel free to exchange the respective lines with the instructions
SET, CLT, BRTS and BRTC to use a bit somewhere in a register. If an error is encountered
the pointer Z points to the point of error. If the error is caused by an illegal character, it points
to that character. If the error is an overflow error, the pointer points to the digit, where the
error occurred.
● Other rules: Further details on the different routines are listed in the general part of the
source code. There you'll find a overview on all rountines, showing all available functions,
their calling conditions and their error cases.

From ASCII to binary


The routine AscToBin2 is suitable for converting ASCII-coded numbers in buffers. It reads over
leading blanks and zeros and stops conversion on the first non-decimal digit read. The length of the
number is limited to the 16-bit long result registers. Numbers that exceed 65,535 cause an error with
the T-flag set and Z placed on the first digit that exceeds the 16-bit limit.

If the length of the ASCII number is exactly five digits, you can use the routine Asc5ToBin2. Every
illegal character causes an error, except leading blanks and zeros.

Conversion is done from the left to the right of the number. Each additional digit causes a
multiplication of the result by 10, followed by adding the digit to the result. The routine is somewhat
slow due to the multiplication by 10. There sure are quicker methods to do the conversion job. But
this one is easy to understand.

From BCD to binary


Conversion of BCDs to binary is similiar to ASCII conversion, so we do not discuss this routine in
detail. See the source code of this routine for additional comments.

Binary multiplication by 10
This routine Bin1Mul10 multiplies a 16-bit-binary in rBin1H:L by 10. To do that, the binary is
copied to another location, added two times with itself, then the copy is added, and another addition
with itself yields the tenfold. As during each step of adding an overflow of the 16-bit-binary can
occur, the detection of the overflow and the following reaction cause the most time and code of that
routine. If you are fine without that level of error detection and if you don't care if your result is ok or
if you prefer error detection a different way, you can skip the parts of the routine that branch around.
The code will be much shorter and faster then.

From binary to ASCII


Conversion from binary to ASCII is done in the routine Bin2ToAsc5. The result is generally five
digits long. The conversion is done by a call to the subroutine Bin2ToBcd5. This is discussed more in
detail below.

If you use the routine Bin2ToAsc instead, the routine returns with the pointer Z on the first non-zero
digit and the number of remaining digits in rBin2L. This is convenient if you have to send the result
via SIO to the man behind the terminal without boring him with leading blanks.

From binary to BCD


Bin2ToBcd5 converts the binary in rBin1H:L to decimal BCD. This conversion is a bit long in code
and required time, but sure easier to understand than others. The conversion is done by repeated
subtraction of binary representations of the decimal numbers 10,000, 1,000, 100 and 10. Only the
remaining one's are treated different!

From binary to Hex


The routine Bin2ToHex4 produces a four digit Hex-ASCII number from a 16-bit binary in rBin1H:L.
Such hex numbers are somewhat easier to read and remember than the binary original. How would
you spell 1011011001011110? Hex B65E is a little bit more convenient to remember, nearly like the
decimal equivalent 46686.

The routine converts the hex digits A to F in capital letters. If you more like a to f, change the source
code accordingly.

From hex to binary


With Hex4ToBin2 the conversion goes the other way round. Because illegal (non-hex) digits can
occur, some code is necessary to detect those errors and signal them in the T-flag.

Zum Seitenanfang

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/CONVERSION.html1/20/2009 7:54:55 PM
Number format conversion in AVR Assembler

Path: Home => AVR-overview => Binary calculations => Number conversion => Source code

Source code of number format conversion


routines
asm-version of this source code: CONVERT.asm

General rules

; ********************************************************
; * Number conversion routines, Version 0.1 January 2002 *
; * (C)2002 by info!at!avr-asm-tutorial.net *
; ********************************************************
;
; The following rules apply for all conversion routines:
; - Errors during conversion set the T-bit in the status
; register.
; - Z points to either SRAM (Z>=$0060) or to registers
; ($0001 .. $001D, exclude R0, R16 and R30/31).
; - ASCII- and BCD-coded numbers with multiple digits are
; placed with higher significant digits at lower adres-
; ses. Z should always point to the most significant
; digit.
; - 16-bit-binary values are generally located in the
; registers rBin1H:rBin1L. These must be defined within
; the calling program.
; - Register rmp (range: R16..R29) is used within the
; routines, its content is changed.
; - Register pair Z is used within the routines, its
; content is set depending on the result.
; - Some routines use register R0 temporarily, its content
; is restored.
; - Due to the use of the Z-Register pair the header file
; for the target processor (xxxxdef.inc) must be inclu-
; ded in the calling program or ZH (R31) and ZL (R30)
; must be defined manually. Otherwise an error message
; results, or you will get crazy things going on, when
; you run the program.
; - Because subroutines and push/pop-operations are used
; within these routines you must set the stack pointer
; (SPH:SPL, resp. SPL for devices with equal or less
; than 256 Byte internal SRAM).
;

Overview on number conversion

;
; ***************** Routines Overview ********************
; Routines Input Conditions Out, Errors
; --------------------------------------------------------
; AscToBin2 Z points on stops at first non- 16-bit-bin
; first ASCII non-decimal digit, rBin1H:L,
; char ignores leading Overflow
; blanks and zeros
; Asc5ToBin2 Z points on requires exact 5 16-bit-bin
; first ASCII valid digits, rBin1H:L,
; char ignores leading Overflow
; blanks and zeros and non-dec
; Bcd5ToBin2 5-digit-BCD requires exact 5 16-bit-bin
; Z points to valid digits rBin1H:L
; first digit Overflow
; and non-BCD
; Bin2ToBcd5 16-bit-bin Z points to first 5-digit-BCD
; in rBin1H:L BCD digit Z on first,
; no errors
; Bin2ToHex4 16-bit-bin Z points to first 4-digit-hex
; in rBin1H:L Hex ASCII digit, Z on first
; hex digits A..F no errors
; Hex4ToBin2 4-digit-hex Z points to first 16-bit-bin
; Z points to hex ASCII digit, rBin1H:L,
; first char requires 4 digits, invalid hex
; A..F or a..f ok digit
; ******************* Conversion code ********************
;
; Package I: From ASCII resp. BCD to binary
;

From ASCII to binary

; AscToBin2
; =========
; converts an ASCII coded number to a 2-Byte bi-
; nary
; In: Z points to first digit, conversion stops at first
; digit detected or if overflow of the result occurs,
; end of number must be terminated by a non-decimal
; ASCII-digit!
; Out: Z points to first non-valid digit or to the digit
; where the overflow occurred, if number is valid the
; T-Flag is clear and the number is in registers
; rBin1H:rBin1L
; Used registers: rBin1H:L (result), rBin2H:L (restored
; after use), rmp
; Called subroutines: Bin1Mul10
;
AscToBin2:
clr rBin1H ; Clear the result
clr rBin1L
clt ; Clear error flag bit
AscToBin2a:
ld rmp,Z+ ; ignore leading blanks and zeros
cpi rmp,' ' ; blank?
breq AscToBin2a
cpi rmp,'0' ; zero?
breq AscToBin2a
AscToBin2b:
subi rmp,'0' ; subtract ASCII zero
brcs AscToBin2d ; End of the number
cpi rmp,10 ; check invalid digit
brcc AscToBin2d ; No-decimal char
rcall Bin1Mul10 ; Multiply binary number by 10
brts AscToBin2c ; overflow, return with T-Flag set
add rBin1L,rmp ; add the digit to the binary
ld rmp,Z+ ; read next char
brcc AscToBin2b ; no overflow to binary MSB
inc rBin1H ; Overflow to binary MSB
brne AscToBin2b ; no overflow of binary MSB
set ; Set overflow flag
AscToBin2c:
sbiw ZL,1 ; Back one char, last char end/invalid
AscToBin2d:
ret
;

5 digit ASCII to binary

; Asc5ToBin2
; ==========
; converts a 5-digit ASCII to a 16-bit-binary
; In: Z points to first decimal ASCII-digit, leading
; blanks and zeros are ok. Requires exact 5 digits.
; Result: T-Flag reports result:
; T=0: result in rBin1H:rBin1L, valid, Z points to
; first digit of the hex-ASCII-number
; T=1: error, Z points to the first illegal character
; or to the digit, where the overflow occurred
; Used registers: rBin1H:L (result), R0 (restored after
; use), rBin2H:L (restored after use), rmp
; Called subroutines: Bin1Mul10
;
Asc5ToBin2:
push R0 ; R0 is used as counter, save it first
ldi rmp,6 ; five chars, one too much
mov R0,rmp
clr rBin1H ; Clear result
clr rBin1L
clt ; Clear T-Bit
Asc5ToBin2a:
dec R0 ; all chars read?
breq Asc5ToBin2d ; last char
ld rmp,Z+ ; read a char
cpi rmp,' ' ; ignore blanks
breq Asc5ToBin2a ; next char
cpi rmp,'0' ; ignore leading zeros
breq Asc5ToBin2a ; next char
Asc5ToBin2b:
subi rmp,'0' ; treat digit
brcs Asc5ToBin2e ; Last char was invalid
cpi rmp,10 ; digit > 9
brcc Asc5ToBin2e ; Last char invalid
rcall Bin1Mul10 ; Multiply result by 10
brts Asc5ToBin2e ; Overflow occurred
add rBin1L,rmp ; add the digit
ld rmp,z+
brcc Asc5ToBin2c ; no overflow to MSB
inc rBin1H ; Overflow to MSB
breq Asc5ToBin2e ; Overflow of MSB
Asc5ToBin2c:
dec R0 ; downcount number of digits
brne Asc5ToBin2b ; convert more chars
Asc5ToBin2d: ; End of ASCII number reached ok
sbiw ZL,5 ; Restore start position of ASCII number
pop R0 ; Restore register R0
ret
Asc5ToBin2e: ; Last char was invalid
sbiw ZL,1 ; Point to invalid char
pop R0 ; Restore register R0
set ; Set T-Flag for error
ret ; and return with error condition set
;

From BCD to binary

; Bcd5ToBin2
; ==========
; converts a 5-bit-BCD to a 16-bit-binary
; In: Z points to the most signifant digit of the BCD
; Out: T-flag shows general result:
; T=0: Binary in rBin1H:L is valid, Z points to the
; first digit of the BCD converted
; T=1: Error during conversion. Either the BCD was too
; big (must be 0..65535, Z points to BCD where the
; overflow occurred) or an illegal BCD was detected
; (Z points to the first non-BCD digit).
; Used registers: rBin1H:L (result), R0 (restored after
; use), rBin2H:L (restored after use), rmp
; Called subroutines: Bin1Mul10
;
Bcd5ToBin2:
push R0 ; Save register
clr rBin1H ; Empty result
clr rBin1L
ldi rmp,5 ; Set counter to 5
mov R0,rmp
clt ; Clear error flag
Bcd5ToBin2a:
ld rmp,Z+ ; Read BCD digit
cpi rmp,10 ; is it valid?
brcc Bcd5ToBin2c ; invalid BCD
rcall Bin1Mul10 ; Multiply result by 10
brts Bcd5ToBin2c ; Overflow occurred
add rBin1L,rmp ; add digit
brcc Bcd5ToBin2b ; No overflow to MSB
inc rBin1H ; Overflow to MSB
breq Bcd5ToBin2c ; Overflow of MSB
Bcd5ToBin2b:
dec R0 ; another digit?
brne Bcd5ToBin2a ; Yes
pop R0 ; Restore register
sbiw ZL,5 ; Set to first BCD digit
ret ; Return
Bcd5ToBin2c:
sbiw ZL,1 ; back one digit
pop R0 ; Restore register
set ; Set T-flag, error
ret ; and return
;

Binary multiplication by 10

; Bin1Mul10
; =========
; multiplies a 16-bit-binary by 10
; Sub used by: AscToBin2, Asc5ToBin2, Bcd5ToBin2
; In: 16-bit-binary in rBin1H:L
; Out: T-flag shows general result:
; T=0: Valid result, 16-bit-binary in rBin1H:L ok
; T=1: Overflow occurred, number too big
;
Bin1Mul10:
push rBin2H ; Save the register of 16-bit-binary 2
push rBin2L
mov rBin2H,rBin1H ; Copy the number
mov rBin2L,rBin1L
add rBin1L,rBin1L ; Multiply by 2
adc rBin1H,rBin1H
brcs Bin1Mul10b ; overflow, get out of here
Bin1Mul10a:
add rBin1L,rbin1L ; again multiply by 2 (4*number reached)
adc rBin1H,rBin1H
brcs Bin1Mul10b ; overflow, get out of here
add rBin1L,rBin2L ; add the copied number (5*number reached)
adc rBin1H,rBin2H
brcs Bin1Mul10b ;overflow, get out of here
add rBin1L,rBin1L ; again multiply by 2 (10*number reached)
adc rBin1H,rBin1H
brcc Bin1Mul10c ; no overflow occurred, don't set T-flag
Bin1Mul10b:
set ; an overflow occurred during multplication
Bin1Mul10c:
pop rBin2L ; Restore the registers of 16-bit-binary 2
pop rBin2H
ret
;
; *************************************************
;
; Package II: From binary to ASCII resp. BCD
;

From binary to ASCII

; Bin2ToAsc5
; ==========
; converts a 16-bit-binary to a 5 digit ASCII-coded decimal
; In: 16-bit-binary in rBin1H:L, Z points to the highest
; of 5 ASCII digits, where the result goes to
; Out: Z points to the beginning of the ASCII string, lea-
; ding zeros are filled with blanks
; Used registers: rBin1H:L (content is not changed),
; rBin2H:L (content is changed), rmp
; Called subroutines: Bin2ToBcd5
;
Bin2ToAsc5:
rcall Bin2ToBcd5 ; convert binary to BCD
ldi rmp,4 ; Counter is 4 leading digits
mov rBin2L,rmp
Bin2ToAsc5a:
ld rmp,z ; read a BCD digit
tst rmp ; check if leading zero
brne Bin2ToAsc5b ; No, found digit >0
ldi rmp,' ' ; overwrite with blank
st z+,rmp ; store and set to next position
dec rBin2L ; decrement counter
brne Bin2ToAsc5a ; further leading blanks
ld rmp,z ; Read the last BCD
Bin2ToAsc5b:
inc rBin2L ; one more char
Bin2ToAsc5c:
subi rmp,-'0' ; Add ASCII-0
st z+,rmp ; store and inc pointer
ld rmp,z ; read next char
dec rBin2L ; more chars?
brne Bin2ToAsc5c ; yes, go on
sbiw ZL,5 ; Pointer to beginning of the BCD
ret ; done
;

Binary to ASCII without leading blanks

; Bin2ToAsc
; =========
; converts a 16-bit-binary to a 5-digit ASCII coded decimal,
; the pointer points to the first significant digit of the
; decimal, returns the number of digits
; In: 16-bit-binary in rBin1H:L, Z points to first digit of
; the ASCII decimal (requires 5 digits buffer space, even
; if the number is smaller!)
; Out: Z points to the first significant digit of the ASCII
; decimal, rBin2L has the number of characters (1..5)
; Used registers: rBin1H:L (unchanged), rBin2H (changed),
; rBin2L (result, length of number), rmp
; Called subroutines: Bin2ToBcd5, Bin2ToAsc5
;
Bin2ToAsc:
rcall Bin2ToAsc5 ; Convert binary to ASCII
ldi rmp,6 ; Counter is 6
mov rBin2L,rmp
Bin2ToAsca:
dec rBin2L ; decrement counter
ld rmp,z+ ; read char and inc pointer
cpi rmp,' ' ; was a blank?
breq Bin2ToAsca ; Yes, was a blank
sbiw ZL,1 ; one char backwards
ret ; done
;

From binary to BCD

; Bin2ToBcd5
; ==========
; converts a 16-bit-binary to a 5-digit-BCD
; In: 16-bit-binary in rBin1H:L, Z points to first digit
; where the result goes to
; Out: 5-digit-BCD, Z points to first BCD-digit
; Used registers: rBin1H:L (unchanged), rBin2H:L (changed),
; rmp
; Called subroutines: Bin2ToDigit
;
Bin2ToBcd5:
push rBin1H ; Save number
push rBin1L
ldi rmp,HIGH(10000) ; Start with tenthousands
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(1000) ; Next with thousands
mov rBin2H,rmp
ldi rmp,LOW(1000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(100) ; Next with hundreds
mov rBin2H,rmp
ldi rmp,LOW(100)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(10) ; Next with tens
mov rBin2H,rmp
ldi rmp,LOW(10)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
st z,rBin1L ; Remainder are ones
sbiw ZL,4 ; Put pointer to first BCD
pop rBin1L ; Restore original binary
pop rBin1H
ret ; and return
;
; Bin2ToDigit
; ===========
; converts one decimal digit by continued subraction of a
; binary coded decimal
; Used by: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc
; In: 16-bit-binary in rBin1H:L, binary coded decimal in
; rBin2H:L, Z points to current BCD digit
; Out: Result in Z, Z incremented
; Used registers: rBin1H:L (holds remainder of the binary),
; rBin2H:L (unchanged), rmp
; Called subroutines: -
;
Bin2ToDigit:
clr rmp ; digit count is zero
Bin2ToDigita:
cp rBin1H,rBin2H ; Number bigger than decimal?
brcs Bin2ToDigitc ; MSB smaller than decimal
brne Bin2ToDigitb ; MSB bigger than decimal
cp rBin1L,rBin2L ; LSB bigger or equal decimal
brcs Bin2ToDigitc ; LSB smaller than decimal
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtract LSB decimal
sbc rBin1H,rBin2H ; Subtract MSB decimal
inc rmp ; Increment digit count
rjmp Bin2ToDigita ; Next loop
Bin2ToDigitc:
st z+,rmp ; Save digit and increment
ret ; done
;
; **************************************************
;
; Package III: From binary to Hex-ASCII
;

From binary to hex

; Bin2ToHex4
; ==========
; converts a 16-bit-binary to uppercase Hex-ASCII
; In: 16-bit-binary in rBin1H:L, Z points to first
; position of the four-character Hex-ASCII
; Out: Z points to the first digit of the four-character
; Hex-ASCII, ASCII digits A..F in capital letters
; Used registers: rBin1H:L (unchanged), rmp
; Called subroutines: Bin1ToHex2, Bin1ToHex1
;
Bin2ToHex4:
mov rmp,rBin1H ; load MSB
rcall Bin1ToHex2 ; convert byte
mov rmp,rBin1L
rcall Bin1ToHex2
sbiw ZL,4 ; Set Z to start
ret
;
; Bin1ToHex2 converts an 8-bit-binary to uppercase hex
; Called by: Bin2ToHex4
;
Bin1ToHex2:
push rmp ; Save byte
swap rmp ; upper to lower nibble
rcall Bin1ToHex1
pop rmp ; Restore byte
Bin1ToHex1:
andi rmp,$0F ; mask upper nibble
subi rmp,-'0' ; add 0 to convert to ASCII
cpi rmp,'9'+1 ; A..F?
brcs Bin1ToHex1a
subi rmp,-7 ; add 7 for A..F
Bin1ToHex1a:
st z+,rmp ; store in target
ret ; and return
;
; *******************************************
;
; Package IV: From Hex-ASCII to binary
;

From hex to binary

; Hex4ToBin2
; converts a 4-digit-hex-ascii to a 16-bit-binary
; In: Z points to first digit of a Hex-ASCII-coded number
; Out: T-flag has general result:
; T=0: rBin1H:L has the 16-bit-binary result, Z points
; to the first digit of the Hex-ASCII number
; T=1: illegal character encountered, Z points to the
; first non-hex-ASCII character
; Used registers: rBin1H:L (result), R0 (restored after
; use), rmp
; Called subroutines: Hex2ToBin1, Hex1ToBin1
;
Hex4ToBin2:
clt ; Clear error flag
rcall Hex2ToBin1 ; convert two digits hex to Byte
brts Hex4ToBin2a ; Error, go back
mov rBin1H,rmp ; Byte to result MSB
rcall Hex2ToBin1 ; next two chars
brts Hex4ToBin2a ; Error, go back
mov rBin1L,rmp ; Byte to result LSB
sbiw ZL,4 ; result ok, go back to start
Hex4ToBin2a:
ret
;
; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
; Called By: Hex4ToBin2
;
Hex2ToBin1:
push R0 ; Save register
rcall Hex1ToBin1 ; Read next char
brts Hex2ToBin1a ; Error
swap rmp; To upper nibble
mov R0,rmp ; interim storage
rcall Hex1ToBin1 ; Read another char
brts Hex2ToBin1a ; Error
or rmp,R0 ; pack the two nibbles together
Hex2ToBin1a:
pop R0 ; Restore R0
ret ; and return
;
; Hex1ToBin1 reads one char and converts to binary
;
Hex1ToBin1:
ld rmp,z+ ; read the char
subi rmp,'0' ; ASCII to binary
brcs Hex1ToBin1b ; Error in char
cpi rmp,10 ; A..F
brcs Hex1ToBin1c ; not A..F
cpi rmp,$30 ; small letters?
brcs Hex1ToBin1a ; No
subi rmp,$20 ; small to capital letters
Hex1ToBin1a:
subi rmp,7 ; A..F
cpi rmp,10 ; A..F?
brcs Hex1ToBin1b ; Error, is smaller than A
cpi rmp,16 ; bigger than F?
brcs Hex1ToBin1c ; No, digit ok
Hex1ToBin1b: ; Error
sbiw ZL,1 ; one back
set ; Set flag
Hex1ToBin1c:
ret ; Return

To the top of that page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html1/20/2009 7:55:01 PM
http://www.avr-asm-tutorial.net/avr_en/source/CONVERT.asm

; ********************************************************
; * Number conversion routines, Version 0.1 January 2002 *
; * (C)2002 by info@avr-asm-tutorial.net *
; ********************************************************
;
; The following rules apply for all conversion routines:
; - Errors during conversion set the T-bit in the status
; register.
; - Z points to either SRAM (Z>=$0060) or to registers
; ($0001 .. $001D, exclude R0, R16 and R30/31).
; - ASCII- and BCD-coded numbers with multiple digits are
; placed with higher significant digits at lower adres-
; ses. Z should always point to the most significant
; digit.
; - 16-bit-binary values are generally located in the
; registers rBin1H:rBin1L. These must be defined within
; the calling program.
; - Register rmp (range: R16..R29) is used within the
; routines, its content is changed.
; - Register pair Z is used within the routines, its
; content is set depending on the result.
; - Some routines use register R0 temporarily, its content
; is restored.
; - Due to the use of the Z-Register pair the header file
; for the target processor (xxxxdef.inc) must be inclu-
; ded in the calling program or ZH (R31) and ZL (R30)
; must be defined manually. Otherwise an error message
; results, or you will get crazy things going on, when
; you run the program.
; - Because subroutines and push/pop-operations are used
; within these routines you must set the stack pointer
; (SPH:SPL, resp. SPL for devices with equal or less
; than 256 Byte internal SRAM).
;
; ***************** Routines Overview ********************
; Routines Input Conditions Out, Errors
; --------------------------------------------------------
; AscToBin2 Z points on stops at first non- 16-bit-bin
; first ASCII non-decimal digit, rBin1H:L,
; char ignores leading Overflow
; blanks and zeros
; Asc5ToBin2 Z points on requires exact 5 16-bit-bin
; first ASCII valid digits, rBin1H:L,
; char ignores leading Overflow
; blanks and zeros and non-dec
; Bcd5ToBin2 5-digit-BCD requires exact 5 16-bit-bin
; Z points to valid digits rBin1H:L
; first digit Overflow
; and non-BCD
; Bin2ToBcd5 16-bit-bin Z points to first 5-digit-BCD
; in rBin1H:L BCD digit Z on first,
; no errors
; Bin2ToHex4 16-bit-bin Z points to first 4-digit-hex
; in rBin1H:L Hex ASCII digit, Z on first
; hex digits A..F no errors
; Hex4ToBin2 4-digit-hex Z points to first 16-bit-bin
; Z points to hex ASCII digit, rBin1H:L,
; first char requires 4 digits, invalid hex
; A..F or a..f ok digit
; ******************* Conversion code ********************
;
; Package I: From ASCII resp. BCD to binary
;
; AscToBin2
; =========
; converts an ASCII coded number to a 2-Byte bi-
; nary
; In: Z points to first digit, conversion stops at first
; digit detected or if overflow of the result occurs,
; end of number must be terminated by a non-decimal
; ASCII-digit!
; Out: Z points to first non-valid digit or to the digit
; where the overflow occurred, if number is valid the
; T-Flag is clear and the number is in registers
; rBin1H:rBin1L
; Used registers: rBin1H:L (result), rBin2H:L (restored
; after use), rmp
; Called subroutines: Bin1Mul10
;
AscToBin2:
clr rBin1H ; Clear the result
clr rBin1L
clt ; Clear error flag bit
AscToBin2a:
ld rmp,Z+ ; ignore leading blanks and zeros
cpi rmp,' ' ; blank?
breq AscToBin2a
cpi rmp,'0' ; zero?
breq AscToBin2a
AscToBin2b:
subi rmp,'0' ; subtract ASCII zero
brcs AscToBin2d ; End of the number
cpi rmp,10 ; check invalid digit
brcc AscToBin2d ; No-decimal char
rcall Bin1Mul10 ; Multiply binary number by 10
brts AscToBin2c ; overflow, return with T-Flag set
add rBin1L,rmp ; add the digit to the binary
ld rmp,Z+ ; read next char
brcc AscToBin2b ; no overflow to binary MSB
inc rBin1H ; Overflow to binary MSB
brne AscToBin2b ; no overflow of binary MSB
set ; Set overflow flag
AscToBin2c:
sbiw ZL,1 ; Back one char, last char end/invalid
AscToBin2d:
ret
;
; Asc5ToBin2
; ==========
; converts a 5-digit ASCII to a 16-bit-binary
; In: Z points to first decimal ASCII-digit, leading
; blanks and zeros are ok. Requires exact 5 digits.
; Result: T-Flag reports result:
; T=0: result in rBin1H:rBin1L, valid, Z points to
; first digit of the hex-ASCII-number
; T=1: error, Z points to the first illegal character
; or to the digit, where the overflow occurred
; Used registers: rBin1H:L (result), R0 (restored after
; use), rBin2H:L (restored after use), rmp
; Called subroutines: Bin1Mul10
;
Asc5ToBin2:
push R0 ; R0 is used as counter, save it first
ldi rmp,6 ; five chars, one too much
mov R0,rmp
clr rBin1H ; Clear result
clr rBin1L
clt ; Clear T-Bit
Asc5ToBin2a:
dec R0 ; all chars read?
breq Asc5ToBin2d ; last char
ld rmp,Z+ ; read a char
cpi rmp,' ' ; ignore blanks
breq Asc5ToBin2a ; next char
cpi rmp,'0' ; ignore leading zeros
breq Asc5ToBin2a ; next char
Asc5ToBin2b:
subi rmp,'0' ; treat digit
brcs Asc5ToBin2e ; Last char was invalid
cpi rmp,10 ; digit > 9
brcc Asc5ToBin2e ; Last char invalid
rcall Bin1Mul10 ; Multiply result by 10
brts Asc5ToBin2e ; Overflow occurred
add rBin1L,rmp ; add the digit
ld rmp,z+
brcc Asc5ToBin2c ; no overflow to MSB
inc rBin1H ; Overflow to MSB
breq Asc5ToBin2e ; Overflow of MSB
Asc5ToBin2c:
dec R0 ; downcount number of digits
brne Asc5ToBin2b ; convert more chars
Asc5ToBin2d: ; End of ASCII number reached ok
sbiw ZL,5 ; Restore start position of ASCII number
pop R0 ; Restore register R0
ret
Asc5ToBin2e: ; Last char was invalid
sbiw ZL,1 ; Point to invalid char
pop R0 ; Restore register R0
set ; Set T-Flag for error
ret ; and return with error condition set
;
; Bcd5ToBin2
; ==========
; converts a 5-bit-BCD to a 16-bit-binary
; In: Z points to the most signifant digit of the BCD
; Out: T-flag shows general result:
; T=0: Binary in rBin1H:L is valid, Z points to the
; first digit of the BCD converted
; T=1: Error during conversion. Either the BCD was too
; big (must be 0..65535, Z points to BCD where the
; overflow occurred) or an illegal BCD was detected
; (Z points to the first non-BCD digit).
; Used registers: rBin1H:L (result), R0 (restored after
; use), rBin2H:L (restored after use), rmp
; Called subroutines: Bin1Mul10
;
Bcd5ToBin2:
push R0 ; Save register
clr rBin1H ; Empty result
clr rBin1L
ldi rmp,5 ; Set counter to 5
mov R0,rmp
clt ; Clear error flag
Bcd5ToBin2a:
ld rmp,Z+ ; Read BCD digit
cpi rmp,10 ; is it valid?
brcc Bcd5ToBin2c ; invalid BCD
rcall Bin1Mul10 ; Multiply result by 10
brts Bcd5ToBin2c ; Overflow occurred
add rBin1L,rmp ; add digit
brcc Bcd5ToBin2b ; No overflow to MSB
inc rBin1H ; Overflow to MSB
breq Bcd5ToBin2c ; Overflow of MSB
Bcd5ToBin2b:
dec R0 ; another digit?
brne Bcd5ToBin2a ; Yes
pop R0 ; Restore register
sbiw ZL,5 ; Set to first BCD digit
ret ; Return
Bcd5ToBin2c:
sbiw ZL,1 ; back one digit
pop R0 ; Restore register
set ; Set T-flag, error
ret ; and return
;
; Bin1Mul10
; =========
; multiplies a 16-bit-binary by 10
; Sub used by: AscToBin2, Asc5ToBin2, Bcd5ToBin2
; In: 16-bit-binary in rBin1H:L
; Out: T-flag shows general result:
; T=0: Valid result, 16-bit-binary in rBin1H:L ok
; T=1: Overflow occurred, number too big
;
Bin1Mul10:
push rBin2H ; Save the register of 16-bit-binary 2
push rBin2L
mov rBin2H,rBin1H ; Copy the number
mov rBin2L,rBin1L
add rBin1L,rBin1L ; Multiply by 2
adc rBin1H,rBin1H
brcs Bin1Mul10b ; overflow, get out of here
Bin1Mul10a:
add rBin1L,rbin1L ; again multiply by 2 (4*number reached)
adc rBin1H,rBin1H
brcs Bin1Mul10b ; overflow, get out of here
add rBin1L,rBin2L ; add the copied number (5*number reached)
adc rBin1H,rBin2H
brcs Bin1Mul10b ;overflow, get out of here
add rBin1L,rBin1L ; again multiply by 2 (10*number reached)
adc rBin1H,rBin1H
brcc Bin1Mul10c ; no overflow occurred, don't set T-flag
Bin1Mul10b:
set ; an overflow occurred during multplication
Bin1Mul10c:
pop rBin2L ; Restore the registers of 16-bit-binary 2
pop rBin2H
ret
;
; *************************************************
;
; Package II: From binary to ASCII resp. BCD
;
; Bin2ToAsc5
; ==========
; converts a 16-bit-binary to a 5 digit ASCII-coded decimal
; In: 16-bit-binary in rBin1H:L, Z points to the highest
; of 5 ASCII digits, where the result goes to
; Out: Z points to the beginning of the ASCII string, lea-
; ding zeros are filled with blanks
; Used registers: rBin1H:L (content is not changed),
; rBin2H:L (content is changed), rmp
; Called subroutines: Bin2ToBcd5
;
Bin2ToAsc5:
rcall Bin2ToBcd5 ; convert binary to BCD
ldi rmp,4 ; Counter is 4 leading digits
mov rBin2L,rmp
Bin2ToAsc5a:
ld rmp,z ; read a BCD digit
tst rmp ; check if leading zero
brne Bin2ToAsc5b ; No, found digit >0
ldi rmp,' ' ; overwrite with blank
st z+,rmp ; store and set to next position
dec rBin2L ; decrement counter
brne Bin2ToAsc5a ; further leading blanks
ld rmp,z ; Read the last BCD
Bin2ToAsc5b:
inc rBin2L ; one more char
Bin2ToAsc5c:
subi rmp,-'0' ; Add ASCII-0
st z+,rmp ; store and inc pointer
ld rmp,z ; read next char
dec rBin2L ; more chars?
brne Bin2ToAsc5c ; yes, go on
sbiw ZL,5 ; Pointer to beginning of the BCD
ret ; done
;
; Bin2ToAsc
; =========
; converts a 16-bit-binary to a 5-digit ASCII coded decimal,
; the pointer points to the first significant digit of the
; decimal, returns the number of digits
; In: 16-bit-binary in rBin1H:L, Z points to first digit of
; the ASCII decimal (requires 5 digits buffer space, even
; if the number is smaller!)
; Out: Z points to the first significant digit of the ASCII
; decimal, rBin2L has the number of characters (1..5)
; Used registers: rBin1H:L (unchanged), rBin2H (changed),
; rBin2L (result, length of number), rmp
; Called subroutines: Bin2ToBcd5, Bin2ToAsc5
;
Bin2ToAsc:
rcall Bin2ToAsc5 ; Convert binary to ASCII
ldi rmp,6 ; Counter is 6
mov rBin2L,rmp
Bin2ToAsca:
dec rBin2L ; decrement counter
ld rmp,z+ ; read char and inc pointer
cpi rmp,' ' ; was a blank?
breq Bin2ToAsca ; Yes, was a blank
sbiw ZL,1 ; one char backwards
ret ; done
;
; Bin2ToBcd5
; ==========
; converts a 16-bit-binary to a 5-digit-BCD
; In: 16-bit-binary in rBin1H:L, Z points to first digit
; where the result goes to
; Out: 5-digit-BCD, Z points to first BCD-digit
; Used registers: rBin1H:L (unchanged), rBin2H:L (changed),
; rmp
; Called subroutines: Bin2ToDigit
;
Bin2ToBcd5:
push rBin1H ; Save number
push rBin1L
ldi rmp,HIGH(10000) ; Start with tenthousands
mov rBin2H,rmp
ldi rmp,LOW(10000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(1000) ; Next with thousands
mov rBin2H,rmp
ldi rmp,LOW(1000)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(100) ; Next with hundreds
mov rBin2H,rmp
ldi rmp,LOW(100)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
ldi rmp,HIGH(10) ; Next with tens
mov rBin2H,rmp
ldi rmp,LOW(10)
mov rBin2L,rmp
rcall Bin2ToDigit ; Calculate digit
st z,rBin1L ; Remainder are ones
sbiw ZL,4 ; Put pointer to first BCD
pop rBin1L ; Restore original binary
pop rBin1H
ret ; and return
;
; Bin2ToDigit
; ===========
; converts one decimal digit by continued subraction of a
; binary coded decimal
; Used by: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc
; In: 16-bit-binary in rBin1H:L, binary coded decimal in
; rBin2H:L, Z points to current BCD digit
; Out: Result in Z, Z incremented
; Used registers: rBin1H:L (holds remainder of the binary),
; rBin2H:L (unchanged), rmp
; Called subroutines: -
;
Bin2ToDigit:
clr rmp ; digit count is zero
Bin2ToDigita:
cp rBin1H,rBin2H ; Number bigger than decimal?
brcs Bin2ToDigitc ; MSB smaller than decimal
brne Bin2ToDigitb ; MSB bigger than decimal
cp rBin1L,rBin2L ; LSB bigger or equal decimal
brcs Bin2ToDigitc ; LSB smaller than decimal
Bin2ToDigitb:
sub rBin1L,rBin2L ; Subtract LSB decimal
sbc rBin1H,rBin2H ; Subtract MSB decimal
inc rmp ; Increment digit count
rjmp Bin2ToDigita ; Next loop
Bin2ToDigitc:
st z+,rmp ; Save digit and increment
ret ; done
;
; **************************************************
;
; Package III: From binary to Hex-ASCII
;
; Bin2ToHex4
; ==========
; converts a 16-bit-binary to uppercase Hex-ASCII
; In: 16-bit-binary in rBin1H:L, Z points to first
; position of the four-character Hex-ASCII
; Out: Z points to the first digit of the four-character
; Hex-ASCII, ASCII digits A..F in capital letters
; Used registers: rBin1H:L (unchanged), rmp
; Called subroutines: Bin1ToHex2, Bin1ToHex1
;
Bin2ToHex4:
mov rmp,rBin1H ; load MSB
rcall Bin1ToHex2 ; convert byte
mov rmp,rBin1L
rcall Bin1ToHex2
sbiw ZL,4 ; Set Z to start
ret
;
; Bin1ToHex2 converts an 8-bit-binary to uppercase hex
; Called by: Bin2ToHex4
;
Bin1ToHex2:
push rmp ; Save byte
swap rmp ; upper to lower nibble
rcall Bin1ToHex1
pop rmp ; Restore byte
Bin1ToHex1:
andi rmp,$0F ; mask upper nibble
subi rmp,-'0' ; add 0 to convert to ASCII
cpi rmp,'9'+1 ; A..F?
brcs Bin1ToHex1a
subi rmp,-7 ; add 7 for A..F
Bin1ToHex1a:
st z+,rmp ; store in target
ret ; and return
;
; *******************************************
;
; Package IV: From Hex-ASCII to binary
;
; Hex4ToBin2
; converts a 4-digit-hex-ascii to a 16-bit-binary
; In: Z points to first digit of a Hex-ASCII-coded number
; Out: T-flag has general result:
; T=0: rBin1H:L has the 16-bit-binary result, Z points
; to the first digit of the Hex-ASCII number
; T=1: illegal character encountered, Z points to the
; first non-hex-ASCII character
; Used registers: rBin1H:L (result), R0 (restored after
; use), rmp
; Called subroutines: Hex2ToBin1, Hex1ToBin1
;
Hex4ToBin2:
clt ; Clear error flag
rcall Hex2ToBin1 ; convert two digits hex to Byte
brts Hex4ToBin2a ; Error, go back
mov rBin1H,rmp ; Byte to result MSB
rcall Hex2ToBin1 ; next two chars
brts Hex4ToBin2a ; Error, go back
mov rBin1L,rmp ; Byte to result LSB
sbiw ZL,4 ; result ok, go back to start
Hex4ToBin2a:
ret
;
; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
; Called By: Hex4ToBin2
;
Hex2ToBin1:
push R0 ; Save register
rcall Hex1ToBin1 ; Read next char
brts Hex2ToBin1a ; Error
swap rmp; To upper nibble
mov R0,rmp ; interim storage
rcall Hex1ToBin1 ; Read another char
brts Hex2ToBin1a ; Error
or rmp,R0 ; pack the two nibbles together
Hex2ToBin1a:
pop R0 ; Restore R0
ret ; and return
;
; Hex1ToBin1 reads one char and converts to binary
;
Hex1ToBin1:
ld rmp,z+ ; read the char
subi rmp,'0' ; ASCII to binary
brcs Hex1ToBin1b ; Error in char
cpi rmp,10 ; A..F
brcs Hex1ToBin1c ; not A..F
cpi rmp,$30 ; small letters?
brcs Hex1ToBin1a ; No
subi rmp,$20 ; small to capital letters
Hex1ToBin1a:
subi rmp,7 ; A..F
cpi rmp,10 ; A..F?
brcs Hex1ToBin1b ; Error, is smaller than A
cpi rmp,16 ; bigger than F?
brcs Hex1ToBin1c ; No, digit ok
Hex1ToBin1b: ; Error
sbiw ZL,1 ; one back
set ; Set flag
Hex1ToBin1c:
ret ; Return

http://www.avr-asm-tutorial.net/avr_en/source/CONVERT.asm1/20/2009 7:55:07 PM
Binary to fixed decimal numbers in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Fixed decimals

Conversion to fixed decimal


numbers in AVR assembler
Sense and Nonsense of floating decimal fractions
First: Do not use any floating points, unless you really need them. Floating points are resource killers
in an AVR, lame ducks und need extreme execution times. Run into this dilemma, if you think
assembler is too complicated, and you prefer Basic or other languages like C and Pascal.
Not so, if you use assembler. You'll be shown here, how you can perform the multiplication of a fixed
point real number in less than 60 micro-seconds, in special cases even within 18 micro-seconds, at 4
Mcs/s clock frequency. Without any floating point processor extensions and other expensive tricks
for people too lazy to use their brain.

How to do that? Back to the roots of math! Most tasks with floating point reals can be done using
integer numbers. Integers are easy to program in assembler and perform fast. The decimal point is
only in the brain of the programmer, and is added somewhere in the decimal digit stream. No one
realizes, that this is a trick.

To the top of that page

Linear conversions
As an example the following task: an 8-Bit-AD-Converter measures an input signal in the range from
0.00 to 2.55 Volt, and returns as the result a binary in the range from $00 and $FF. The result, a
voltage, is to be displayed on a LCD display. Silly example, as it is so easy: The binary is converted
to a decimal ASCII string between 000 and 255, and just behind the first digit the decimal point has
to be inserted. Done!

The electronics world sometimes is more complicated. E.g., the AD-Converter returns an 8-Bit-Hex
for input voltages between 0.00 and 5.00 Volt. Now we're tricked and do not know how to proceed.
To display the correct result on the LCD we would have to multiply the binary by 500/255, which is
1.9608. This is a silly number, as it is almost 2, but only almost. And we don't want that kind of
inaccuracy of 2%, while we have an AD-converter with around 0.25% accuracy.

To cope with this, we multiply the input by 500/255*256 or 501.96 and divide the result by 256. Why
first multiply by 256 and then divide by 256? It's just for enhanced accuracy. If we multiply the input
by 502 instead of 501.96, the error is just in the order of 0.008%. That is good enough for our AD-
converter, we can live with that. And dividing by 256 is an easy task, because it is a well-known
power of 2. By dividing with number that are a power of 2, the AVR feels very comfortable and
performs very fast. By dividing with 256, the AVR is even faster, because we just have to skip the
last byte of the binary number. Not even shift and rotate!

The multiplication of an 8-bit-binary with the 9-bit-binary 502 (hex 1F6) can have a result greater
than 16 bits. So we have to reserve 24 bits or 3 registers for the result. During multiplication, the
constant 502 has to be shifted left (multiplication by 2) to add these numbers to the result each time a
one rolls out of the input number. As this might need eight shifts left, we need futher three bytes for
this constant. So we chose the following combination of registers for the multiplication:
Number Value (example) Register
Input value 255 R1
Multiplicator 502 R4:R3:R2
Result 128,010 R7:R6:R5
After filling the value 502 (00.01.F6) to R4:R3:R2 and clearing the result registers R7:R6:R5 the
multiplication goes like this:

1. Test, if the input number is already zero. If yes, we're done.


2. If no, one bit of the input number is shifted out of the register to the right, into the carry, while
a zero is stuffed into bit 7. This instruction is named Logical-Shight-Right or LSR.
3. If the bit in carry is a one, we add the multiplicator (during step 1 the value 502, in step 2 it's
1004, a.s.o.) to the result. During adding, we care for any carry (adding R2 to R5 by ADD,
adding R3 to R6 and R4 to R7 with the ADC instruction!). If the bit in the carry was a zero,
we just don't add the multiplicator to the result and jump to the next step.
4. Now the multiplicator is multiplied by 2, because the next bit shifted out of the input number
is worth double as much. So we shift R2 to the left (by inserting a zero in bit 0) using LSL. Bit
7 is shifted to the carry. Then we rotate this carry into R3, rotating its content left one bit, and
bit 7 to the carry. The same with R4.
5. Now we're done with one digit of the input number, and we proceed with step 1 again.

The result of the multiplication by 502 now is in the result registers R7:R6:R5. If we just ignore
register R5 (division by 256), we have our desired result. To enhance occuracy, we can use bit 7 in
R5 to round the result. Now we just have to convert the result from its binary form to decimal ASCII
(see Conversion bin to decimal-ASCII). If we just add a decimal point in the right place in the ASCII
string, our voltage string is ready for the display.

The whole program, from the input number to the resulting ASCII string, requires between 79 and
228 clock cycles, depending from the input number. Those who want to beat this with the floating
point routine of a more sophisticated language than assembler, feel free to mail me your conversion
time (and program flash and memory usage).

To the top of that page

Example 1: 8-bit-AD-converter with fixed decimal output


The program described above is, a little optimized, available in HTML-form or as assembler source
code file. The source has all necessary routines for the conversion in a compact form, to be exported
to other programs. The head of the program is a test setting, so you can test the program in the
simulator.

To the top of that page

Example 2: 10-bit-AD-converter with fixed decimal output


8-bit-AD-converters are rare, 10 bits are more often used. Because 10 bits are more accurate, the
conversion is done to yield a four-digit-decimal. Don't be surprised, if the last digit is not very stable.
Here we have the HTML-form and here is the assembler source code file of the program.

Caused by the expanded accuracy, the program needs some more registers. It is a bit slower, but not
much. I still keep up with the above offer for Basic, C and Pascal programers, if you beat this.

To the top of that page

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/FPCONV.html1/20/2009 7:55:11 PM
8-bit-binary to 3-digit-decimal-fixed in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Fixed decimal => 8-bit-conversion

8-bit binary conversion to 3-digit


fixed decimal in AVR Assembler

; Demonstrates floating point conversion


; in Assembler, (C)2003 www.avr-asm-tutorial.net
;
; The task: You read in an 8-bit result of an
; analogue-digital-converter, number is in the
; range from hex 00 to FF.
; You need to convert this into a floating point
; number in the range from 0.00 to 5.00 Volt
;
; The program scheme:
; 1. Multiplication by 502 (hex 01F6).
; That step multiplies by 500, 256 and
; divides by 255 in one step!
; 2. Round the result and cut the last byte
; of the result.
; This step divides by 256 by ignoring the
; last byte of the result. Before doing
; that, bit 7 is used to round the result.
; 3. Convert the resulting word to ASCII and set
; the correct decimal sign
; The resulting word in the range from 0 to
; 500 is displayed in ASCII-characters as
; 0.00 to 5.00.
;
; The registers used:
; The routines use the registers R8..R1 without
; saving these before. Also required is a multi-
; purpose register called rmp, located in the
; upper half of the registers. Please take care
; that these registers don't conflict with the
; register use in the rest of your program.
;
; When entering the routine the 8-bit number is
; expected in the register R1.
; The multiplication uses R4:R3:R2 to hold
; the multiplicator 502 (is shifted left
; max. eight times during multiplication).
; The result of the multiplication is calculated
; in the registers R7:R6:R5.
; The result of the so called division by 256
; by just ignoring R5 in the result, is in
; R7:R6. R7:R6 is rounded, depending on the
; highest bit of R5, and the result is copied to
; R2:R1.
; Conversion to an ASCII-string uses the input
; in R2:R1, the register pair R4:R3 as a divisor
; for conversion, and places the ASCII result
; string to R5:R6:R7:R8 (R6 is the decimal char).
;
; Other conventions:
; The conversion uses subroutines and the stack.
; The stack must work fine for the use of three
; levels (six bytes SRAM).
;
; Conversion times:
; The whole routine requires 228 clock cycles
; maximum (converting $FF), and 79 clock cycles
; minimum (converting $00). At 4 MHz the times
; are 56.75 microseconds resp. 17.75 microseconds.
;
; Definitions:
; Registers
.DEF rmp = R16 ; used as multi-purpose register
;
; AVR type
; Tested for type AT90S8515, only required for
; stack setting, routines work fine with other
; AT90S-types also
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start of test program
;
; Just writes a number to R1 and starts the
; conversion routine, for test purposes only
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Convert $FF
mov R1,rmp
rcall fpconv8 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
;
; Conversion routine wrapper, calls the different conversion steps
;
fpconv8:
rcall fpconv8m ; multiplicate by 502
rcall fpconv8r ; round and divide by 256
rcall fpconv8a ; convert to ASCII string
ldi rmp,'.' ; set decimal char
mov R6,rmp
ret ; all done
;
; Subroutine multiplication by 502
;
; Starting conditions:
; +--+
; |R1| Input number, example is $FF
; |FF|
; +--+
; +--+--+--+
; |R4|R3|R2| Multiplicant 502 = $00 01 F6
; |00|01|F6|
; +--+--+--+
; +--+--+--+
; |R7|R6|R5| Result, as example 128,010
; |01|F4|0A|
; +--+--+--+
;
fpconv8m:
clr R4 ; set the multiplicant to 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; clear the result
clr R6
clr R5
fpconv8m1:
or R1,R1 ; check if the number is all zeros
brne fpconv8m2 ; still one's, go on convert
ret ; ready, return back
fpconv8m2:
lsr R1 ; shift number to the right (div by 2)
brcc fpconv8m3 ; if the lowest bit was 0, then skip adding
add R5,R2 ; add the number in R6:R5:R4:R3 to the result
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; multiply R4:R3:R2 by 2
rol R3
rol R4
rjmp fpconv8m1 ; repeat for next bit
;
; Round the value in R7:R6 with the value in bit 7 of R5
;
fpconv8r:
clr rmp ; put zero to rmp
lsl R5 ; rotate bit 7 to carry
adc R6,rmp ; add LSB with carry
adc R7,rmp ; add MSB with carry
mov R2,R7 ; copy the value to R2:R1 (divide by 256)
mov R1,R6
ret
;
; Convert the word in R2:R1 to an ASCII string in R5:R6:R7:R8
;
; +--+--+
; +R2|R1| Input value 0..500
; +--+--+
; +--+--+
; |R4|R3| Decimal divider value
; +--+--+
; +---+---+---+---+
; | R5| R6| R7| R8| Resulting ASCII string (for input value 5,00)
; |'5'|'.'|'0'|'0'|
; +---+---+---+---+
;
fpconv8a:
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; get ASCII digit by repeated subtraction
mov R5,rmp ; set hundreds string char
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv8d ; get the next ASCII digit
mov R7,rmp ; set tens string char
ldi rmp,'0' ; convert the rest to an ASCII char
add rmp,R1
mov R8,rmp ; set ones string char
ret
;
; Convert binary word in R2:R1 to a decimal digit by substracting
; the decimal divider value in R4:R3 (100, 10)
;
fpconv8d:
ldi rmp,'0' ; start with decimal value 0
fpconv8d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv8d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv8d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; up one digit
rjmp fpconv8d1 ; once again
;
; End of floating point conversion routines
;
;
; End of conversion test routine
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/FP_CONV8_EN.html1/20/2009 7:55:14 PM
http://www.avr-asm-tutorial.net/avr_en/source/FP_CONV8_EN.asm

; Demonstrates floating point conversion


; in Assembler, (C)2003 www.avr-asm-tutorial.net
;
; The task: You read in an 8-bit result of an
; analogue-digital-converter, number is in the
; range from hex 00 to FF.
; You need to convert this into a floating point
; number in the range from 0.00 to 5.00 Volt
;
; The program scheme:
; 1. Multiplication by 502 (hex 01F6).
; That step multiplies by 500, 256 and
; divides by 255 in one step!
; 2. Round the result and cut the last byte
; of the result.
; This step divides by 256 by ignoring the
; last byte of the result. Before doing
; that, bit 7 is used to round the result.
; 3. Convert the resulting word to ASCII and set
; the correct decimal sign
; The resulting word in the range from 0 to
; 500 is displayed in ASCII-characters as
; 0.00 to 5.00.
;
; The registers used:
; The routines use the registers R8..R1 without
; saving these before. Also required is a multi-
; purpose register called rmp, located in the
; upper half of the registers. Please take care
; that these registers don't conflict with the
; register use in the rest of your program.
;
; When entering the routine the 8-bit number is
; expected in the register R1.
; The multiplication uses R4:R3:R2 to hold
; the multiplicator 502 (is shifted left
; max. eight times during multiplication).
; The result of the multiplication is calculated
; in the registers R7:R6:R5.
; The result of the so called division by 256
; by just ignoring R5 in the result, is in
; R7:R6. R7:R6 is rounded, depending on the
; highest bit of R5, and the result is copied to
; R2:R1.
; Conversion to an ASCII-string uses the input
; in R2:R1, the register pair R4:R3 as a divisor
; for conversion, and places the ASCII result
; string to R5:R6:R7:R8 (R6 is the decimal char).
;
; Other conventions:
; The conversion uses subroutines and the stack.
; The stack must work fine for the use of three
; levels (six bytes SRAM).
;
; Conversion times:
; The whole routine requires 228 clock cycles
; maximum (converting $FF), and 79 clock cycles
; minimum (converting $00). At 4 MHz the times
; are 56.75 microseconds resp. 17.75 microseconds.
;
; Definitions:
; Registers
.DEF rmp = R16 ; used as multi-purpose register
;
; AVR type
; Tested for type AT90S8515, only required for
; stack setting, routines work fine with other
; AT90S-types also
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start of test program
;
; Just writes a number to R1 and starts the
; conversion routine, for test purposes only
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Convert $FF
mov R1,rmp
rcall fpconv8 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
;
; Conversion routine wrapper, calls the different conversion steps
;
fpconv8:
rcall fpconv8m ; multiplicate by 502
rcall fpconv8r ; round and divide by 256
rcall fpconv8a ; convert to ASCII string
ldi rmp,'.' ; set decimal char
mov R6,rmp
ret ; all done
;
; Subroutine multiplication by 502
;
; Starting conditions:
; +--+
; |R1| Input number, example is $FF
; |FF|
; +--+
; +--+--+--+
; |R4|R3|R2| Multiplicant 502 = $00 01 F6
; |00|01|F6|
; +--+--+--+
; +--+--+--+
; |R7|R6|R5| Result, as example 128,010
; |01|F4|0A|
; +--+--+--+
;
fpconv8m:
clr R4 ; set the multiplicant to 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; clear the result
clr R6
clr R5
fpconv8m1:
or R1,R1 ; check if the number is all zeros
brne fpconv8m2 ; still one's, go on convert
ret ; ready, return back
fpconv8m2:
lsr R1 ; shift number to the right (div by 2)
brcc fpconv8m3 ; if the lowest bit was 0, then skip adding
add R5,R2 ; add the number in R6:R5:R4:R3 to the result
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; multiply R4:R3:R2 by 2
rol R3
rol R4
rjmp fpconv8m1 ; repeat for next bit
;
; Round the value in R7:R6 with the value in bit 7 of R5
;
fpconv8r:
clr rmp ; put zero to rmp
lsl R5 ; rotate bit 7 to carry
adc R6,rmp ; add LSB with carry
adc R7,rmp ; add MSB with carry
mov R2,R7 ; copy the value to R2:R1 (divide by 256)
mov R1,R6
ret
;
; Convert the word in R2:R1 to an ASCII string in R5:R6:R7:R8
;
; +--+--+
; +R2|R1| Input value 0..500
; +--+--+
; +--+--+
; |R4|R3| Decimal divider value
; +--+--+
; +---+---+---+---+
; | R5| R6| R7| R8| Resulting ASCII string (for input value 5,00)
; |'5'|'.'|'0'|'0'|
; +---+---+---+---+
;
fpconv8a:
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; get ASCII digit by repeated subtraction
mov R5,rmp ; set hundreds string char
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv8d ; get the next ASCII digit
mov R7,rmp ; set tens string char
ldi rmp,'0' ; convert the rest to an ASCII char
add rmp,R1
mov R8,rmp ; set ones string char
ret
;
; Convert binary word in R2:R1 to a decimal digit by substracting
; the decimal divider value in R4:R3 (100, 10)
;
fpconv8d:
ldi rmp,'0' ; start with decimal value 0
fpconv8d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv8d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv8d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; up one digit
rjmp fpconv8d1 ; once again
;
; End of floating point conversion routines
;
;
; End of conversion test routine
;

http://www.avr-asm-tutorial.net/avr_en/source/FP_CONV8_EN.asm1/20/2009 7:55:15 PM
10-bit-binary to 4-digit-decimal-fixed in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Fixed decimal => 10-bit-conversion

10-bit binary to 4-digit fixed decimal


conversion in AVR Assembler

; Demonstrates floating point conversion


; in Assembler, (C)2003 www.avr-asm-tutorial.net
;
; The task: You read in a 10-bit result of an
; analogue-digital-converter, number is in the
; range from hex 0000 to 03FF.
; You need to convert this into a floating point
; number in the range from 0.000 to 5.000 Volt
;
; The program scheme:
; 1. Check that the number is smaller than $0400.
; Prevent illegal overflows during the
; following multiplication.
; 2. Multiplication by 320,313 (hex 04E338).
; That step multiplies by 5,000, 65536 and
; divides by 1023 in one step!
; 3. Round the result and cut the last two bytes
; of the result.
; This step divides by 65536 by ignoring the
; last two bytes of the result. Before doing
; that, bit 15 is used to round the result.
; 4. Convert the resulting word to ASCII and set
; the correct decimal point
; The resulting word in the range from 0 to
; 5.000 is displayed in ASCII-characters
;
; The registers used:
; The routines use the registers R10..R1 without
; saving these before. Also required is a multi-
; purpose register called rmp, located in the
; upper half of the registers. Please take care
; that this register doesn't conflict with the
; register use in the rest of your program.
;
; When entering the routine the 10-bit number is
; expected in the register pair R2:R1.
; If the number is greater than $03FF then the
; check routine returns with the carry flag set,
; and the resulting string in R5:R6:R7:R8:R9:R10
; is set to the null-terminated ASCII-string
; "E.EEEE".
; The multiplication uses R6:R5:R4:R3 to hold
; the multiplicator 320.313 (is shifted left
; max. ten times during multiplication)
; The result of the multiplication is calculated
; in the registers R10:R9:R8:R7.
; The result of the so called division by 65536
; by just ignoring R8:R7 in the result, is in
; R10:R9. R10:R9 is rounded, depending on the
; highest bit of R8, and the result is copied to
; R2:R1.
; Conversion to an ASCII-string uses the input
; in R2:R1, the register pair R4:R3 as a divisor
; for conversion, and places the ASCII result
; string to R5:R6:R7:R8:R9:R10 (null-terminated).
;
; Other conventions:
; The conversion uses subroutines and the stack.
; The stack must work fine for the use of three
; levels (six bytes SRAM).
;
; Conversion times:
; The whole routine requires 326 clock cycles
; maximum (converting $03FF), and 111 clock cycles
; minimum (converting $0000). At 4 MHz the times
; are 81.25 microseconds resp. 27.5 microseconds.
;
; Definitions:
; Registers
.DEF rmp = R16 ; used as multi-purpose register
;
; AVR type
; Tested for type AT90S8515, only required for
; stack setting, routines work fine with other
; AT90S-types also
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start of test program
;
; Just writes a number to R2:R1 and starts the
; conversion routine, for test purposes only
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$03 ; Convert $03FF
mov R2,rmp
ldi rmp,$FF
mov R1,rmp
rcall fpconv10 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
;
; Conversion routine wrapper, calls the different conversion steps
;
fpconv10:
rcall fpconv10c ; Check the input value in R2:R1
brcs fpconv10e ; if carry set, set "E.EEE"
rcall fpconv10m ; multiplicate by 320,313
rcall fpconv10r ; round and divide by 65536
rcall fpconv10a ; convert to ASCII string
rjmp fpconv10f ; set decimal point and null-termination
fpconv10e:
ldi rmp,'E' ; set error condition to result string
mov R5,rmp
mov R7,rmp
mov R8,rmp
mov R9, rmp
fpconv10f:
ldi rmp,'.' ; set decimal point
mov R6,rmp
clr rmp ; null-terminate ASCII string
mov R10,rmp
ret ; all done
;
; Subroutine inputcheck
;
fpconv10c:
ldi rmp,$03 ; compare MSB with 03
cp rmp,R2 ; if R2>$03, set carry on return
ret
;
; Subroutine multiplication by 320,313
;
; Starting conditions:
; +---+---+
; | R2+ R1| Input number
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplicant 320.313 = $00 04 E3 38
; | 00| 04| E3| 38|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Result
; | 00| 00| 00| 00|
; +---+---+---+---+
;
fpconv10m:
clr R6 ; set the multiplicant to 320.313
ldi rmp,$04
mov R5,rmp
ldi rmp,$E3
mov R4,rmp
ldi rmp,$38
mov R3,rmp
clr R10 ; clear the result
clr R9
clr R8
clr R7
fpconv10m1:
mov rmp,R1 ; check if the number is clear
or rmp,R2 ; any bit of the word a one?
brne fpconv10m2 ; still one's, go on convert
ret ; ready, return back
fpconv10m2:
lsr R2 ; shift MSB to the right (div by 2)
ror R1 ; rotate LSB to the right and set bit 7
brcc fpconv10m3 ; if the lowest bit was 0, then skip adding
add R7,R3 ; add the number in R6:R5:R4:R3 to the result
adc R8,R4
adc R9,R5
adc R10,R6
fpconv10m3:
lsl R3 ; multiply R6:R5:R4:R3 by 2
rol R4
rol R5
rol R6
rjmp fpconv10m1 ; repeat for next bit
;
; Round the value in R10:R9 with the value in bit 7 of R8
;
fpconv10r:
clr rmp ; put zero to rmp
lsl R8 ; rotate bit 7 to carry
adc R9,rmp ; add LSB with carry
adc R10,rmp ; add MSB with carry
mov R2,R10 ; copy the value to R2:R1 (divide by 65536)
mov R1,R9
ret
;
; Convert the word in R2:R1 to an ASCII string in R5:R6:R7:R8:R9:R10
;
; +---+---+
; + R2| R1| Input value 0..5,000
; +---+---+
; +---+---+
; | R4| R3| Decimal divider value
; +---+---+
; +---+---+---+---+---+---+
; | R5| R6| R7| R8| R9|R10| Resulting ASCII string (for input value
5,000)
; |'5'|'.'|'0'|'0'|'0'|$00| null-terminated
; +---+---+---+---+---+---+
;
fpconv10a:
ldi rmp,HIGH(1000) ; Set the decimal divider value to 1,000
mov R4,rmp
ldi rmp,LOW(1000)
mov R3,rmp
rcall fpconv10d ; get ASCII digit by repeated subtraction
mov R5,rmp ; set thousands string char
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv10d ; get the next ASCII digit
mov R7,rmp ; set hundreds string char
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv10d ; get the next ASCII digit
mov R8,rmp ; set tens string char
ldi rmp,'0' ; convert the rest to an ASCII char
add rmp,R1
mov R9,rmp ; set ones string char
ret
;
; Convert binary word in R2:R1 to a decimal digit by substracting
; the decimal divider value in R4:R3 (1000, 100, 10)
;
fpconv10d:
ldi rmp,'0' ; start with decimal value 0
fpconv10d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv10d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv10d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; up one digit
rjmp fpconv10d1 ; once again
;
; End of floating point conversion routines
;
;
; End of conversion test routine
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/FP_CONV10_EN.html1/20/2009 7:55:17 PM
http://www.avr-asm-tutorial.net/avr_en/source/FP_CONV10_EN.asm

; Demonstrates floating point conversion


; in Assembler, (C)2003 www.avr-asm-tutorial.net
;
; The task: You read in a 10-bit result of an
; analogue-digital-converter, number is in the
; range from hex 0000 to 03FF.
; You need to convert this into a floating point
; number in the range from 0.000 to 5.000 Volt
;
; The program scheme:
; 1. Check that the number is smaller than $0400.
; Prevent illegal overflows during the
; following multiplication.
; 2. Multiplication by 320,313 (hex 04E338).
; That step multiplies by 5,000, 65536 and
; divides by 1023 in one step!
; 3. Round the result and cut the last two bytes
; of the result.
; This step divides by 65536 by ignoring the
; last two bytes of the result. Before doing
; that, bit 15 is used to round the result.
; 4. Convert the resulting word to ASCII and set
; the correct decimal point
; The resulting word in the range from 0 to
; 5.000 is displayed in ASCII-characters
;
; The registers used:
; The routines use the registers R10..R1 without
; saving these before. Also required is a multi-
; purpose register called rmp, located in the
; upper half of the registers. Please take care
; that this register doesn't conflict with the
; register use in the rest of your program.
;
; When entering the routine the 10-bit number is
; expected in the register pair R2:R1.
; If the number is greater than $03FF then the
; check routine returns with the carry flag set,
; and the resulting string in R5:R6:R7:R8:R9:R10
; is set to the null-terminated ASCII-string
; "E.EEEE".
; The multiplication uses R6:R5:R4:R3 to hold
; the multiplicator 320.313 (is shifted left
; max. ten times during multiplication)
; The result of the multiplication is calculated
; in the registers R10:R9:R8:R7.
; The result of the so called division by 65536
; by just ignoring R8:R7 in the result, is in
; R10:R9. R10:R9 is rounded, depending on the
; highest bit of R8, and the result is copied to
; R2:R1.
; Conversion to an ASCII-string uses the input
; in R2:R1, the register pair R4:R3 as a divisor
; for conversion, and places the ASCII result
; string to R5:R6:R7:R8:R9:R10 (null-terminated).
;
; Other conventions:
; The conversion uses subroutines and the stack.
; The stack must work fine for the use of three
; levels (six bytes SRAM).
;
; Conversion times:
; The whole routine requires 326 clock cycles
; maximum (converting $03FF), and 111 clock cycles
; minimum (converting $0000). At 4 MHz the times
; are 81.25 microseconds resp. 27.5 microseconds.
;
; Definitions:
; Registers
.DEF rmp = R16 ; used as multi-purpose register
;
; AVR type
; Tested for type AT90S8515, only required for
; stack setting, routines work fine with other
; AT90S-types also
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start of test program
;
; Just writes a number to R2:R1 and starts the
; conversion routine, for test purposes only
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$03 ; Convert $03FF
mov R2,rmp
ldi rmp,$FF
mov R1,rmp
rcall fpconv10 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
;
; Conversion routine wrapper, calls the different conversion steps
;
fpconv10:
rcall fpconv10c ; Check the input value in R2:R1
brcs fpconv10e ; if carry set, set "E.EEE"
rcall fpconv10m ; multiplicate by 320,313
rcall fpconv10r ; round and divide by 65536
rcall fpconv10a ; convert to ASCII string
rjmp fpconv10f ; set decimal point and null-termination
fpconv10e:
ldi rmp,'E' ; set error condition to result string
mov R5,rmp
mov R7,rmp
mov R8,rmp
mov R9, rmp
fpconv10f:
ldi rmp,'.' ; set decimal point
mov R6,rmp
clr rmp ; null-terminate ASCII string
mov R10,rmp
ret ; all done
;
; Subroutine inputcheck
;
fpconv10c:
ldi rmp,$03 ; compare MSB with 03
cp rmp,R2 ; if R2>$03, set carry on return
ret
;
; Subroutine multiplication by 320,313
;
; Starting conditions:
; +---+---+
; | R2+ R1| Input number
; +---+---+
; +---+---+---+---+
; | R6| R5| R4| R3| Multiplicant 320.313 = $00 04 E3 38
; | 00| 04| E3| 38|
; +---+---+---+---+
; +---+---+---+---+
; |R10| R9| R8| R7| Result
; | 00| 00| 00| 00|
; +---+---+---+---+
;
fpconv10m:
clr R6 ; set the multiplicant to 320.313
ldi rmp,$04
mov R5,rmp
ldi rmp,$E3
mov R4,rmp
ldi rmp,$38
mov R3,rmp
clr R10 ; clear the result
clr R9
clr R8
clr R7
fpconv10m1:
mov rmp,R1 ; check if the number is clear
or rmp,R2 ; any bit of the word a one?
brne fpconv10m2 ; still one's, go on convert
ret ; ready, return back
fpconv10m2:
lsr R2 ; shift MSB to the right (div by 2)
ror R1 ; rotate LSB to the right and set bit 7
brcc fpconv10m3 ; if the lowest bit was 0, then skip adding
add R7,R3 ; add the number in R6:R5:R4:R3 to the result
adc R8,R4
adc R9,R5
adc R10,R6
fpconv10m3:
lsl R3 ; multiply R6:R5:R4:R3 by 2
rol R4
rol R5
rol R6
rjmp fpconv10m1 ; repeat for next bit
;
; Round the value in R10:R9 with the value in bit 7 of R8
;
fpconv10r:
clr rmp ; put zero to rmp
lsl R8 ; rotate bit 7 to carry
adc R9,rmp ; add LSB with carry
adc R10,rmp ; add MSB with carry
mov R2,R10 ; copy the value to R2:R1 (divide by 65536)
mov R1,R9
ret
;
; Convert the word in R2:R1 to an ASCII string in R5:R6:R7:R8:R9:R10
;
; +---+---+
; + R2| R1| Input value 0..5,000
; +---+---+
; +---+---+
; | R4| R3| Decimal divider value
; +---+---+
; +---+---+---+---+---+---+
; | R5| R6| R7| R8| R9|R10| Resulting ASCII string (for input value 5,000)
; |'5'|'.'|'0'|'0'|'0'|$00| null-terminated
; +---+---+---+---+---+---+
;
fpconv10a:
ldi rmp,HIGH(1000) ; Set the decimal divider value to 1,000
mov R4,rmp
ldi rmp,LOW(1000)
mov R3,rmp
rcall fpconv10d ; get ASCII digit by repeated subtraction
mov R5,rmp ; set thousands string char
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv10d ; get the next ASCII digit
mov R7,rmp ; set hundreds string char
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv10d ; get the next ASCII digit
mov R8,rmp ; set tens string char
ldi rmp,'0' ; convert the rest to an ASCII char
add rmp,R1
mov R9,rmp ; set ones string char
ret
;
; Convert binary word in R2:R1 to a decimal digit by substracting
; the decimal divider value in R4:R3 (1000, 100, 10)
;
fpconv10d:
ldi rmp,'0' ; start with decimal value 0
fpconv10d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv10d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv10d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; up one digit
rjmp fpconv10d1 ; once again
;
; End of floating point conversion routines
;
;
; End of conversion test routine
;

http://www.avr-asm-tutorial.net/avr_en/source/FP_CONV10_EN.asm1/20/2009 7:55:20 PM
Hardware multiplication in AVR Assembler

Path: Home => AVR-Overview => Binary calculations => Hardware Multiplication

Binary hardware multiplication in AVR Assembler

All ATmega, AT90CAN and AT90PWM have an on-board hardware multiplicator, that performs 8 by 8 bit multiplications in only two clock cycles. So whenever
you have to do multiplications and you are sure that this software never ever needs not to run on an AT90S- or ATtiny-chip, you can make use of this hardware
feature. This page shows how to do it.
The sections are:

1. 8-by-8-binaries
2. 16-by-8-binaries
3. 16-by-16-binaries
4. 16-by-24-binaries

1. Hardware multiplication of 8-by-8-bit binaries


The use is simple and straight-forward: if the two binaries to be multiplied are in the registers R16 and R17, just type

mul R16,R17

As the result of these two 8-bit binaries might be up two 16 bits long, the result will be in the registers R1 (most significant byte) and R0 (least significant byte).
That's all about it.

The program demonstrates the simulation in the Studio. It multiplies


decimal 250 (hex FA) by decimal 100 (hex 64), in the registers R16 and
R17.

The registers R0 (LSB) and R1 (MSB) hold the result hex 61A8 or decimal 25,000.

And: yes, that requires only two cycles, or 2 microseconds with a 1 Mcs/s clock.

To the top of that page

2. Hardware multiplication of a 16- by an 8-bit-binary


You have a larger binary to multiply? Hardware is limited to 8, so we need to invest some genious ideas instead. To solve the problem with larger binaries, we just
look at this combination of 16 and 8 first. Understanding this concept helps understanding the method, so you will be able to solve the 32-by-64-bit multiplication
problem later.

First the math: a 16-bit-binary are simply two 8-bit-binaries, where the most significant
one of these two is multiplied by decimal 256 or hex 100. For those who need a reminder:
the decimal 1234 is simply (12 multiplied by 100) plus 34, or (1 multiplied by 1000) plus
(2 multiplied by 100) plus (3 multiplied by 10) plus 4. So the 16-bit-binary m1 is equal to
256*m1M plus m1L, where m1M is the MSB and m1L is the LSB. Multiplying m1 by 8-
bit-binary m2 so is, mathmatically formulated:

m1 * m2 = (256*m1M + m1L) * m2, or 256*m1M*m2 + m1L*m2

So we just need to do two multiplications and to add both results. Sorry, if you see three
asterisks in the formula: the multiplication with 256 in the binary world doesn't require any hardware at all, because it is a simple move to the next higher byte. Just
like the multiplication by 10 in the decimal world is simply moving the number one left and write a zero to the least significant digit.

So let's go to a practical example. First we need some registers to

1. load the numbers m1 and m2,


2. provide space for the result, which might have 24 bits length.

;
; Test hardware multiplication 16-by-8-bit
;
; Register definitions:
;
.def Res1 = R2
.def Res2 = R3
.def Res3 = R4
.def m1L = R16
.def m1M = R17
.def m2 = R18

First we load the numbers:

;
; Load Registers
;
.equ m1 = 10000
;
ldi m1M,HIGH(m1) ; upper 8 bits of m1 to m1M
ldi m1L,LOW(m1) ; lower 8 bits of m1 to m1L
ldi m2,250 ; 8-bit constant to m2

The two numbers are loaded into R17:R16 (dec 10000 = hex 2710) and R18 (dec 250 = hex FA).

Then we multiply the LSB first:

;
; Multiply
;
mul m1L,m2 ; Multiply LSB
mov Res1,R0 ; copy result to result register
mov Res2,R1

The LSB multiplication of hex 27 by hex FA yields hex 0F0A, written to the registers R00 (LSB, hex A0) and
R01 (MSB, hex 0F). The result is copied to the lower two bytes of the result register, R3:R2.

Now the multiplication of the MSB of m1 with m2 follows:

mul m1M,m2 ; Multiply MSB

The multiplication of the MSB of m1, hex 10, with m2, hex FA, yields hex 2616 in R1:R0.

Now two steps are performed at once: multiplication by 256 and adding the result to the previous result. This is done by adding R1:R0 to Res3:Res2 instead of Res2:
Res1. R1 can just be copied to Res3. R0 is added to Res2 then. If the carry is set after adding, the next higher byte Res3 is increased by one.

mov Res3,R1 ; copy MSB result to result byte 3


add Res2,R0 ; add LSB result to result byte 2
brcc NoInc ; if not carry, jump
inc Res3
NoInc:

The result in R4:R3:R2 is hex 2625A0, which is decimal 2500000 (as everybody knows), and is obviously
correct.

The cycle counter of the multiplication points to 10, at 1 Mcs/s clock a total of 10 microseconds. Very much
faster than software multiplication!

To the top of that page

3. Hardware multiplication of a 16- by a 16-bit-binary


Now that we have understood the principle, it should be easy to do 16-by-16. The result requires four bytes now (Res4:Res3:Res2:Res1, located in R5:R4:R3:R2).
The formula is:

m1 * m2 = (256*m1M + m1L) * (256*m2M + m2L) = 65536*m1M*m2M +


256*m1M*m2L + 256*m1L*m2M + m1L*m2L

Obviously four multiplications now. We start with the first and the last as the two easiest
ones: their results are simply copied to the correct result register positions. The results of
the two multiplications in the middle of the formula have to be added to the middle of our
result registers, with possible carry overflows to the most significant byte of the result. To
do that, you will see a simple trick that is easy to understand. The software:

;
; Test Hardware Multiplication 16 by 16
;
; Define Registers
;
.def Res1 = R2
.def Res2 = R3
.def Res3 = R4
.def Res4 = R5
.def m1L = R16
.def m1M = R17
.def m2L = R18
.def m2M = R19
.def tmp = R20
;
; Load input values
;
.equ m1 = 10000
.equ m2 = 25000
;
ldi m1M,HIGH(m1)
ldi m1L,LOW(m1)
ldi m2M,HIGH(m2)
ldi m2L,LOW(m2)
;
; Multiply
;
clr R20 ; clear for carry operations
mul m1M,m2M ; Multiply MSBs
mov Res3,R0 ; copy to MSW Result
mov Res4,R1
mul m1L,m2L ; Multiply LSBs
mov Res1,R0 ; copy to LSW Result
mov Res2,R1
mul m1M,m2L ; Multiply 1M with 2L
add Res2,R0 ; Add to Result
adc Res3,R1
adc Res4,tmp ; add carry
mul m1L,m2M ; Multiply 1L with 2M
add Res2,R0 ; Add to Result
adc Res3,R1
adc Res4,tmp
;
; Multiplication done
;

Simulation shows the following steps. Loading the two constants 10000 (hex 2710) and 25000 (hex 61A8) to the registers in the upper register space ...

Multiplying the two MSBs (hex 27 and 61) and copying the result in R1:R0 to the two most upper result
registers R5:R4 ...

Multiplying the two LSBs (hex 10 and A8) and copying the result in R1:R0 to the two lower result registers
R3:R2 ...

Multiplying the MSB of m1 with the LSB of m2 and adding the result in R1:R0 to the result register's two
middle bytes, no carry occurred ...

Multiplying the LSB of m1 with the MSB of m2 and adding the result in R1:R0 to the result register's two
middle bytes, no carry occurred. The result is hex 0EE6B280, which is 250000000 and obviously correct ...

Multiplication needed 19 clock cycles, which is very much faster than with software multiplication. Another
advantage here: the required time is ALWAYS exactly 19 cycles, and it doesn't depend on the input numbers
(like is the case with software multiplication and on overflow occurances (thanks to our small trick of adding
zero with carry). So you can rely on this ...

To the top of that page

4. Hardware multiplication of a 16- by a 24-bit-binary


The multiplication of a 16 bit binary "a" with a 24
bit binary "b" leads to results with up to 40 bit
length. The multiplication scheme requires six 8-
by-8-bit multiplications and adding the results to
the appropriate position in the result registers. The
assembler source code for this:

; Hardware Multiplication 16 by
24 bit
.include "m8def.inc"
;
; Register definitions
.def a1 = R2 ; define 16-bit
register
.def a2 = R3
.def b1 = R4 ; define 24-bit
register
.def b2 = R5
.def b3 = R6
.def e1 = R7 ; define 40-bit result register
.def e2 = R8
.def e3 = R9
.def e4 = R10
.def e5 = R11
.def c0 = R12 ; help register for adding
.def rl = R16 ; load register
;
; Load constants
.equ a = 10000 ; multiplicator a, hex 2710
.equ b = 1000000 ; multiplicator b, hex 0F4240
ldi rl,BYTE1(a) ; load a
mov a1,rl
ldi rl,BYTE2(a)
mov a2,rl
ldi rl,BYTE1(b) ; load b
mov b1,rl
ldi rl,BYTE2(b)
mov b2,rl
ldi rl,BYTE3(b)
mov b3,rl
;
; Clear registers
clr e1 ; clear result registers
clr e2
clr e3
clr e4
clr e5
clr c0 ; clear help register
;
; Multiply
mul a2,b3 ; term 1
add e4,R0 ; add to result
adc e5,R1
mul a2,b2 ; term 2
add e3,R0
adc e4,R1
adc e5,c0 ; (add possible carry)
mul a2,b1 ; term 3
add e2,R0
adc e3,R1
adc e4,c0
adc e5,c0
mul a1,b3 ; term 4
add e3,R0
adc e4,R1
adc e5,c0
mul a1,b2 ; term 5
add e2,R0
adc e3,R1
adc e4,c0
adc e5,c0
mul a1,b1 ; term 6
add e1,R0
adc e2,R1
adc e3,c0
adc e4,c0
adc e5,c0
;
; done.
nop
; Result should be hex 02540BE400

The complete execution requires

● 10 clock cycles for loading the constants,


● 6 clock cycles for clearing registers, and
● 33 clock cycles for multiplication.

To the top of that page

©2008 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/calc/HARDMULT.html1/20/2009 7:55:44 PM
AVR-Tutorial

Path: Home => AVR-Overview => Tutorial

Tutorial for learning assembly language


for the
AVR-Single-Chipprocessor AT90Sxxxx
of ATMEL with practical examples.
Simple introduction examples,
Tutorial

(For downloading the *.asm-files click the link while holding the shift-key down.)
HTML- ASM-
What to learn here ...
Format Format
Learn to handle the board, output to the board LEDs via a port, basic structure of
Test1 Test1 the assembly language, assembler directives and command. The LEDs will go on
and off with 800 Hertz (what a useful example).
Reading input from a port, call a subroutine, setup and use of the stack by
subroutines, binary math operations (AND, OR, ROL, etc.), branching and
Test2 Test2 conditions (SBIx, BRxx). Pressing key 0 and 1 on the board should light up the
LEDs 0 and 1, one of the other keys the LEDs 2 to 6, pressing key 7 shuts all the
LEDs down (also a rather useful program).
Read the timer in polling mode, use the MOV command. A loop in the main
program reads the hardware counter until it reaches zero, increments a software
Test3 Test3
counter and displays its content in hex on the LEDs of the board (at least
something like a clock).
Timer in interrupt mode, use interrupts, interrupt vectors, BCD-arithmetic. The
main program loop waits until the upper byte of a software counter reaches hex
3D. Then it waits until the timer low byte reaches 09 (one second = 15625
Test4 Test4 decimal = 3D09 hex counter pulses). The counters are reset to zero and the
second counter is incremented. The seconds are displayed on the LEDs as packed
BCD digits (one digit=4 bits, one byte represents two digits). The seconds are
reset to zero, if 60 is reached. The seconds are output for the LEDs.

Back to the AVR index page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_TUT.html1/20/2009 7:55:48 PM
AVR-Tutorium, Teil 1

Path: Home => AVR-Overview => Tutorial => Part 1

; Test 1: Learn to know parts of the board


hardware output to the LEDs

; What to learn here:


; - to access a output-port (Port B and the LEDs)
; - the different parts of a typical assembler program

; General conventions used here:


; - Words in uppercase letters are command words of the assembler language
; or predefined ports of the processor.
; - Words in lowercase letters are defined by me.

; Assembler directive: define the target chip type

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; The directives NOLIST and LIST switch off the listing of the INCLUDE-file
; (the listing will be found in the file TEST1.LST).

; Define register
;
; This register is defined for the purpose of interim storage of values.
; The .DEF statement renames one of the 32 8-bit registers to a easier
; to remember name (here: mp). It is easier to use than its real name
; R16. Renaming these register also has the advantage that whenever you
; want to change such a location you'll just have to change the .DEF
; statement. Otherwise you would have to go through all commands re-
; ferencing the register R16 and change all these lines.

.DEF mp = R16

; Restart
;
; Up till now not one byte of code was created. Here we start with the
; first code, we define the program start adress. Later we will see, that
; this jump command at adress 0 is useful. Here the first byte of code is
; created.
; Whenever the AVR is restarted it starts its program execution at adress
; 0000. Such a restart may be activated by a power-on, by a hardware
; reset on the respective pin or by a watchdog-timer reaching its zero
; count. (The watchdog timer is not used here.)
; In all these cases a jump to a program called "main" will be executed.
; RJMP means "Relative Jump". In a relative jump a relative distance
; is added to the current execution adress and the program is executed
; at this new adress. We don't have to care about this distance by now
; because the assembler calculates this relative distance from the information
; in our source code and adds it automatically - as long as the maximum
; permissible distance of 2 kB for- or backwards is not exceeded, otherwise
; the assembler stops with an error message.

RJMP main

; Here we start with our main program code. First we have to define a
; label, because the assembler has to know that this is the target of a
; jump. A label is a freely defined name, followed by ":". For a better
; overview labels start in column 1 of a line, all commands start with a
; blank or a tab character. Behind the label there could be a command,
; but this is not used here.

main:

; First we need to define port B as output, because the LEDs are connected
; to these port pins. This is done by writing eight ones to the data direction
; register of port B. The data direction register of port B is named DDRB,
; we don't have to care about its real adress, as the .def-file holds this
; information already. We do that in two steps. First we load binary 1111.1111
; to a register:

LDI mp,0b11111111

; The command LDI (LoaD Immediate) loads an 8-bit value into the register
; mp. This command is only valid for the registers R16 to R31. That is why we
; defined mp that way at the beginning of this source code file. Commands
; with two parameters are generally defined such that the first parameter
; is the target (here: register mp), where the result of the operation goes to.
; The second parameter is the value or location where the result comes from.
; After execution of this command the register mp has the value 1111.1111
; binary, FF hex or 255 decimal.
; The 0b... of the beginning of the number is always a binary, 0x... is a hex
; notation. The leading zero is the signal for the assembler to expect a number,
; not a register or something else. Numbers without 0b... or 0x.. are decimal
; by default. (LDI mp,255 would have the same result.)

; This value has to be brought to the data direction register of port B now
; to make all port pins to outputs. A 1 in the data direction register brings
; the pin to switch on its output drivers, a zero makes it an input.

OUT DDRB,mp

; The command OUT writes register values (here: mp or R16) to a port


; (here DDRB). DDRB is defined in the file "8515def.inc", which is already
; read by the assembler when the .DEVICE-command or the .INCLUDE-
; command above has been processed. So we don't need to care here
; for the real adress of this port.

; The following part of the program now writes zeros and ones to the port.
; The LEDs are switched on and off with a high frequency. Because this
; part of the program is repeated over and over again, I called it loop.
; The label loop is jumped to whenver the processing of writing ones and
; zeros is ended.

loop:
LDI mp,0x00
OUT PORTB,mp

; LDI load eight zero bits to the universial register mp. OUT copies these
; zeros to the port B. This time they are written to the port's output register
; named PORTB.
; The zeros set the LEDs on, because they are connected to the supply
; voltage over resistors of 1 k (0=on, 1=off).

LDI mp,0xFF
OUT PORTB,mp

; After that eight ones are loaded into the register mp and copied to
; the same data port. That switches the LEDs off.

RJMP loop

; With this relative jump we jump back to the start of the loop and the
; loop is repeated as long as power is supplied.
; At 4 MHz xtal frequency every LDI- and OUT-command execution requires
; 250 ns, the RJMP need 2 cycles and 500 ns. Every 1,500 ns the loop is
; executed once, so with these values the LEDs are switched at 667 kHz.

; After assembling this sourcefile the program will have eight words.
; The file TEST1.LST holds the result of the assembling process in form
; of a listing.

; This was the first lecture, wait for more ...

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TEST1.html1/20/2009 7:55:53 PM
http://www.avr-asm-tutorial.net/avr_en/source/TEST1.asm

; Test 1: Learn to know parts of the board hardware output to the LEDs.
; What to learn here:
; - to access a output-port (Port B and the LEDs)
; - the different parts of a typical assembler program
; General conventions used here:
; - Words in uppercase letters are command words of the assembler language
; or predefined ports of the processor.
; - I define Words in lowercaseletters.
; Assembler directive: define the target chip type
;
; Usually you do not have to include the def.inc-file. But my installation
; does not find the definition files in the proper subdirectory. So I include
; it manually by adding these lines to my source code. Failure to include
; these definitions would result in a number of error messages. Simply
; copy the def.inc-file to the same directory where your source code resides
; or add your whole path to the include-statement below.
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; The directives NOLIST and LIST switch off the listing of the INCLUDE-file
; (the listing will be found in the file TEST1.LST).
; Define register
;
; This register is defined for the purpose of interim storage of values.
; The .DEF statement renames one of the 32 8-bit registers to a easier
; to remember name (here: mp). It is easier to use than its real name
; R16. Renaming these register also has the advantage that whenever you
; want to change such a location you'll just have to change the .DEF
; statement. Otherwise you would have to go through all commands re-
; ferencing the register R16 and change all these lines.
.DEF mp = R16
; Restart
;
; Up till now not one byte of code was created. Here we start with the
; first code, we define the program start adress. Later we will see, that
; this jump command at adress 0 is useful. Here the first byte of code is
; created.
; Whenever the AVR is restarted it starts its program execution at adress
; 0000. Such a restart may be activated by a power-on, by a hardware
; reset on the respective pin or by a watchdog-timer reaching its zero
; count. (The watchdog timer is not used here.)
; In all these cases a jump to a program called "main" will be executed.
; RJMP means "Relative Jump". In a relative jump a relative distance
; is added to the current execution adress and the program is executed
; at this new adress. We don't have to care about this distance by now
; because the assembler calculates this relative distance from the information
; in our source code and adds it automatically - as long as the maximum
; permissible distance of 2 kB for- or backwards is not exceeded, otherwise
; the assembler stops with an error message.
rjmp main
; Here we start with our main program code. First we have to define a
; label, because the assembler has to know that this is the target of a
; jump. A label is a freely defined name, followed by ":". For a better
; overview labels start in column 1 of a line, all commands start with a
; blank or a tab character. Behind the label there could be a command,
; but this is not used here.
main:
; First we need to define port B as output, because the LEDs are connected
; to these port pins. This is done by writing eight ones to the data direction
; register of port B. The data direction register of port B is named DDRB,
; we don't have to care about its real adress, as the .def-file holds this
; information already. We do that in two steps. First we load binary 1111.1111
; to a register:
ldi mp,0b11111111
; The command LDI (LoaD Immediate) loads an 8-bit value into the register
; mp. This command is only valid for the registers R16 to R31. That is why we
; defined mp that way at the beginning of this source code file. Commands
; with two parameters are generally defined such that the first parameter
; is the target (here: register mp), where the result of the operation goes to.
; The second parameter is the value or location where the result comes from.
; After execution of this command the register mp has the value 1111.1111
; binary, FF hex or 255 decimal.
; The 0b... of the beginning of the number is always a binary, 0x... is a hex
; notation. The leading zero is the signal for the assembler to expect a number,
; not a register or something else. Numbers without 0b... or 0x.. are decimal
; by default. (LDI mp,255 would have the same result.)
; This value has to be brought to the data direction register of port B now
; to make all port pins to outputs. A 1 in the data direction register brings
; the pin to switch on its output drivers, a zero makes it an input.
out DDRB,mp
; The command OUT writes register values (here: mp or R16) to a port
; (here DDRB). DDRB is defined in the file "8515def.inc", which is already
; read by the assembler when the .DEVICE-command or the .INCLUDE-
; command above has been processed. So we don't need to care here
; for the real adress of this port.
; The following part of the program now writes zeros and ones to the port.
; The LEDs are switched on and off with a high frequency. Because this
; part of the program is repeated over and over again, I called it loop.
; The label loop is jumped to whenver the processing of writing ones and
; zeros is ended.
loop:
ldi mp,0x00
out PORTB,mp
; LDI load eight zero bits to the universial register mp. OUT copies these
; zeros to the port B. This time they are written to the port's output register
; named PORTB.
; The zeros set the LEDs on, because they are connected to the supply
; voltage over resistors of 1 k (0=on, 1=off).
ldi mp,0xFF
out PORTB,mp
; After that eight ones are loaded into the register mp and copied to
; the same data port. That switches the LEDs off.
rjmp loop
; With this relative jump we jump back to the start of the loop and the
; loop is repeated as long as power is supplied.
; At 4 MHz xtal frequency every LDI- and OUT-command execution requires
; 250 ns, the RJMP need 2 cycles and 500 ns. Every 1,500 ns the loop is
; executed once, so with these values the LEDs are switched at 667 kHz.
;
; After assembling this sourcefile the program will have eight words.
; The file TEST1.LST holds the result of the assembling process in form
; of a listing.
; This was the first lecture, wait for more ...

http://www.avr-asm-tutorial.net/avr_en/source/TEST1.asm1/20/2009 7:55:57 PM
AVR-Tutorial, part 2

Path: Home => AVR-Overview => Tutorial => Part 2

; Test 2: Learn to more about the board: Input


from a port

; What to learn here:


; - to read input from a port
; - call subroutines and setup the stack
; - Binary math operations like AND, OR, ROL, etc.
; - Conditional branches (commands SBIx, BRxx)

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Define a universal register:

.DEF mp = R16

; The jump-command on adress 0 again:

RJMP main

; The main program starts here:

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer


OUT SPL,mp
LDI mp,HIGH(RAMEND)
OUT SPH,mp

These commands initiate the stack in the build in SRAM. Stack operations
; are always necessary when subroutines or interrupts are called.
; By calling the subroutine or interrupt handling routine the actual adress
; is written to the stack in order to later jump back to the code where the
; interrupt or call occurred. The stack is located at the upper end of the
; build in SRAM. The upper end of the SRAM is called RAMEND and is defined
; in the file "xxxxdef.inc" for the respective processor type, so we do not
; have to care about its real value.
; If a byte is disposed on the stack it is written to the SRAM location and the
; stack pointer at adress SPH:SPL (a 16 bit value) is decremented to the next
; lower stack location. Further disposing bytes brings this pointer nearer
; to the beginning of the SRAM. If a byte is taken from the stack then the
; stackpointer is incremented first and then the value is read.
; The last value put on the stack is read first when the stack is read, called
; a Last-In-First-Out structure.
; As the program counter and the adress structure requires 16 bits and
; all registers and the SRAM are 8 bits wide, every adress on stack requires
; two write/read operations to process the 16 bits. The SRAM adress is 16
; bits wide, so the port SPL holds the lower 8 bits and the port SPH holds
; the upper eight bits of the stack adress. Togeter we get the pointer SPH:SPL
; as a 16 bit pointer to the stack adress.
; The operations LOW and HIGH provide the opportunity to commincate to
; the assembler that the lower or upper byte of RAMEND is meant when
; we set up the stack pointer ports with the RAMEND value.

; Port D is connected to the eight switches on the board. In order to


; read these switches these pins have to have a zero in their data direction
; register

LDI mp,0x00 ; 8 zeros in universal register


OUT DDRD,mp ; to data direction register

; The switches connect the inputs of port D with GND. In order to provide
; a clear logical 1 when the key is open pull-up resistors have to be added.
; On board the STK200 are external pull-ups, so we don't need the internal
; resistors. Those resistors are build in the chip, so we can switch them
; on by software action. This is done by writing ones to the port register:

LDI mp,0xFF ; 8 Ones into the universal register


OUT PORTD,mp ; and to port D (these are the pull-ups now!)

; Port B connected to the LEDs is again output, so we need to set its direction
; register.lOn startup we want the LEDs to be all off, so we need to write ones
; to the port output registers, too.

LDI mp,0xFF ; 8 Ones to the universal register


OUT DDRB,mp ; and to the data direction register
OUT PORTB,mp ; and to the output registers.

; Clicking the keys 0 and 1 should switch on the corresponding LEDs,


; the keys 2 to 6 all the other LEDs. Clicking key 7 swiches all LEDs off.
; Within the main loop the switches are read and, if the different conditions
; are met, branched to the different subroutines.

loop:

; Reading switch 0 (very easy first)


; The first command (SBIS) reads port D (PIND) and tests if the bit 0 is
; one. If so, the next command is skipped. This is the case, if the switch
; is open and the input pin is pulled to one by the pull-up. If the switch
; is on, the pin reports zero and the condition for branching is not fulfilled.
; So the next command after SBIS must be a single byte command that
; branches to the routine that sets LED 0 on. This must be a subroutine,
; as it has to come back after execution, because we have to process the
; other switches as well.
; This subroutine is further down in the source code, the assembler cares
; about the displacement for the RCALL command. The RCALL pushes the
; current adress on stack, so the subroutine can come back to the next
; byte to be processed. The RCALL is used here, because it is a single
; byte command, while a normal CALL command, also implemented in the
; AVRs, is a 2-byte-command and would not fit.

SBIS PIND,0 ; Jump if bit 0 in port D input is one


RCALL Lampe0 ; Relative call to the subroutine named Lampe0

; After processing the subroutine and by jumping over that call command
; the next command is processed.

; Reading switch 1 (a little bit exotic)


; The ports are mirrored into the adress space of the SRAM. The SRAM
; adress is 32 bytes higher than the respective port adress (add hex 20).
; So we can use SRAM read commands to access the port. For our
; convenience we give that adress a new name:

.EQU d_in_spiegel=PIND + $20

; With the register pair R27:R26 we define a pointer that points to that input
; port. With the LoaD-command we read the port input to a register as if it
; were a SRAM byte.

LDI R26,LOW(d_in_spiegel) ; define lower pointer in R26


LDI R27,HIGH(d_in_spiegel) ; define upper pointer in R27
LD mp,X ; Laad register mp from pointer adress (PIND)

; Isolate Pin1 (the switch 1) using mit AND-command and test for all zeros

ANDI mp,0b00000010 ; AND Bit 1

; Branch over all following commands if the result of the AND command is
; not zero (switch was off, input was one). The jump command BRNE (branch
; if not equal) branches to a lable up- or downwards and is not limited to
; a single byte command to follow. Use it for bigger jumps (here we don't).

BRNE weiter ; branch to lablel weiter, if not zero


RCALL Lampe1 ; Relative call to subroutine Lampe1

; Switches 2 to 6
; Read the ports D into a register, mask the switches 0, 1 and 7 with the
; OR command and isolate the switches 2 to 6, if all are ones skip the next
; commands with the BREQ command to the label sw7, otherwise read the
; current status of the LEDs on port B (PINB), set all pins from 2 to 7 to zeros
; and send this to the port B output.

weiter: IN mp,PIND ; Read port D


ORI mp,0b10000011 ; mask switches 0, 1 und 7
CPI mp,0b11111111 ; any one switch on?
BREQ sw7 ; branch to label sw7, if not (= $FF)
IN mp,PINB ; read current LED-status
ANDI mp,0b00000011 ; switch on lamps 2 bis 7
OUT PORTB,mp ; to LED-port

sw7: IN mp,PIND ; read port with the switches


ROL mp ; shift the seventh bit into the carry-flag
BRCS endloop ; 7th bit is 1 (BRanch if carry is set)
LDI mp,0xFF ; All LEDs off
OUT PORTB,mp

endloop:
RJMP loop

; Subroutine Lampe0

; switches LED 0 on.

Lampe0: IN mp,PINB ; Read current status on port B


ANDI mp,0b11111110 ; Whatever the other LEDs might be, this is 0
OUT PORTB,mp ; write back the result to the LED port
RET ; get the return adress from the stack and return where you came from.

; Subroutine Lampe1

; switches LED1 on (a little bit different than Lampe0)

Lampe1: IN mp,PINB ; read status of port B


CBR mp,0b00000010 ; set bit 1 to zero with the CBR command
OUT PORTB,mp ; write back the result to the LEDs
RET ; return adress from stack and return

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TEST2.html1/20/2009 7:56:02 PM
http://www.avr-asm-tutorial.net/avr_en/source/TEST2.asm

; Test 2: Learn to more about the board: Input from a port


; What to learn here:
; - to read input from a port
; - call subroutines and setup the stack
; - Binary math operations like AND, OR, ROL, etc.
; - Conditional branches (commands SBIx, BRxx)
; This is the replacement for the malfunctioning .DEVICE directive again:
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Define a universal register:
.DEF mp = R16
; The jump-command on adress 0 again:
rjmp main
; The main program starts here
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp
ldi mp,HIGH(RAMEND)
out SPH,mp
; These commands initiate the stack in the build in SRAM. Stack operations
; are always necessary when subroutines or interrupts are called.
; By calling the subroutine or interrupt handling routine the actual adress
; is written to the stack in order to later jump back to the code where the
; interrupt or call occurred. The stack is located at the upper end of the
; build in SRAM. The upper end of the SRAM is called RAMEND and is defined
; in the file "xxxxdef.inc" for the respective processor type, so we do not
; have to care about its real value.
; If a byte is disposed on the stack it is written to the SRAM location and the
; stack pointer at adress SPH:SPL (a 16 bit value) is decremented to the next
; lower stack location. Further disposing bytes brings this pointer nearer
; to the beginning of the SRAM. If a byte is taken from the stack then the
; stackpointer is incremented first and then the value is read.
; The last value put on the stack is read first when the stack is read, called
; a Last-In-First-Out structure.
; As the program counter and the adress structure requires 16 bits and
; all registers and the SRAM are 8 bits wide, every adress on stack requires
; two write/read operations to process the 16 bits. The SRAM adress is 16
; bits wide, so the port SPL holds the lower 8 bits and the port SPH holds
; the upper eight bits of the stack adress. Togeter we get the pointer SPH:SPL
; as a 16 bit pointer to the stack adress.
; The operations LOW and HIGH provide the opportunity to commincate to
; the assembler that the lower or upper byte of RAMEND is meant when
; we set up the stack pointer ports with the RAMEND value.
; Port D is connected to the eight switches on the board. In order to
; read these switches these pins have to have a zero in their data direction
; register
ldi mp,0x00 ; 8 zeros in universal register
out DDRD,mp ; to data direction register
; The switches connect the inputs of port D with GND. In order to provide
; a clear logical 1 when the key is open pull-up resistors have to be added.
; This is already done on the STK200 by external resistors, so we wouldn't
; need to use the internal resistors.Those internal resistors are build on
; the chip, so we can switch them on by software action. This is done by
; writing ones to the port register:
ldi mp,0xFF ; 8 Ones into the universal register
out PORTD,mp ; and to port D (these are the pull-ups now!)
; Port B connected to the LEDs is again output, so we need to set its direction
; register. On startup we want the LEDs to be all off, so we need to write ones
; to the port output registers, too.
ldi mp,0xFF ; 8 Ones to the universal register
out DDRB,mp ; and to the data direction register
out PORTB,mp ; and to the outputregisters.
; Clicking the keys 0 and 1 should switch on the corresponding LEDs,
; the keys 2 to 6 all the other LEDs. Clicking key 7 swiches all LEDs off.
; Within the main loop the switches are read and, if the different conditions
; are met, branched to the different subroutines.
loop:
; Reading switch 0 (very easy first)
; The first command (SBIS) reads port D (PIND) and tests if the bit 0 is
; one. If so, the next command is skipped. This is the case, if the switch
; is open and the input pin is pulled to one by the pull-up. If the switch
; is on, the pin reports zero and the condition for branching is not fulfilled.
; So the next command after SBIS must be a single byte command that
; branches to the routine that sets LED 0 on. This must be a subroutine,
; as it has to come back after execution, because we have to process the
; other switches as well.
; This subroutine is further down in the source code, the assembler cares
; about the displacement for the RCALL command. The RCALL pushes the
; current adress on stack, so the subroutine can come back to the next
; byte to be processed. The RCALL is used here, because it is a single
; byte command, while a normal CALL command, also implemented in the
; AVRs, is a 2-byte-command and would not fit.
sbis PIND,0 ; Jump if bit 0 in port D input is one
rcall Lampe0 ; Relative call to the subroutine named Lampe0
; After processing the subroutine and by jumping over that call command
; the next command is processed.
; Reading switch 1 (a little bit exotic)
; The ports are mirrored into the adress space of the SRAM. The SRAM
; adress is 32 bytes higher than the respective port adress (add hex 20).
; So we can use SRAM read commands to access the port. For our
; convenience we give that adress a new name:
.EQU d_in_spiegel=PIND + $20
; With the register pair R27:R26 we define a pointer that points to that input
; port. With the LoaD-command we read the port input to a register as if it
; were a SRAM byte.
ldi R26,LOW(d_in_spiegel) ; define lower pointer in R26
ldi R27,HIGH(d_in_spiegel) ; define upper pointer in R27
ld mp,X ; Laad register mp from pointer adress (PIND)
; Isolate Pin1 (the switch 1) using mit AND-command and test for all zeros
andi mp,0b00000010 ; AND Bit 1
; Branch over all following commands if the result of the AND command is
; not zero (switch was off, input was one). The jump command BRNE (branch
; if not equal) branches to a lable up- or downwards and is not limited to
; a single byte command to follow. Use it for bigger jumps (here we don't).
brne weiter ; branch to lablel weiter, if not zero
rcall Lampe1 ; Relative call to subroutine Lampe1
; Switches 2 to 6
; Read the ports D into a register, mask the switches 0, 1 and 7 with the
; OR command and isolate the switches 2 to 6, if all are ones skip the next
; commands with the BREQ command to the label sw7, otherwise read the
; current status of the LEDs on port B (PINB), set all pins from 2 to 7 to zeros
; and send this to the port B output.
weiter:
in mp,PIND ; Read port D
ori mp,0b10000011 ; mask switches 0, 1 und 7
cpi mp,0b11111111 ; any one switch on?
breq sw7 ; branch to label sw7, if not (= $FF)
in mp,PINB ; read current LED-status
andi mp,0b00000011 ; switch on lamps 2 bis 7
out PORTB,mp ; to LED-port
sw7:
in mp,PIND ; read port with the switches
rol mp ; shift the seventh bit into the carry-flag
brcs endloop ; 7th bit is 1 (BRanch if carry is set)
ldi mp,0xFF ; All LEDs off
out PORTB,mp
endloop:
rjmp loop
; Subroutine Lampe0
; switches LED 0 on.
Lampe0:
in mp,PINB ; Read current status on port B
andi mp,0b11111110 ; Whatever the other LEDs might be, this is 0
out PORTB,mp ; write back the result to the LED port
ret ; get the return adress from the stack and return where you came from.
; Subroutine Lampe1
; switches LED1 on (a little bit different than Lampe0)
Lampe1:
in mp,PINB ; read status of port B
cbr mp,0b00000010 ; set bit 2 to zero with the CBR command
out PORTB,mp ; write back the result to the LEDs
ret ; return adress from stack and return

http://www.avr-asm-tutorial.net/avr_en/source/TEST2.asm1/20/2009 7:56:07 PM
AVR-Tutorial, part 3

Path: Home => AVR-Overview => Tutorial => Part 3

; Test 3: Learn more about the timer in polling


mode

; New things to learn here:


; - Timer in polling mode
; - MOV-command

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; universal register definition

.DEF mp = R16

; Counter for the number of time-outs of the timer

.DEF z1 = R0

; Reset-vector to adress 0000

RJMP main

; Main program starts here:

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer (Unterprogramme!)


OUT SPL,mp
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Set software counter-register to zero

LDI mp,0 ; z1 is not directly accessible, so we first


MOV z1,mp ; write the zero to mp and copy that

; Prescaler of the timer = 1024, 4 MHz/1024 = 3906,25 Hz


; this equals a timer tick every 256 µs
LDI mp,0x05 ;Initiate Timer/Counter 0 prescaler
OUT TCCR0,mp ; to Timer 0 Control Register

; Port B is LED-port

LDI mp,0xFF ; all bits are output


OUT DDRB,mp ; to data direction register

; Main program loop reads the counter until he reaches zero,


; the software counter in incremented and displayed on the LEDs.
; 256 Timer ticks equal 65.536 ms or a frequency of 15.25878906 Hz.
loop:
IN mp,TCNT0 ; read the 8-bit timer 0
CPI mp,0 ; test for zero
BRNE loop ; if not zero, return to the loop
RCALL IncZ1 ; call subroutine software-counter-incrementation
RCALL Display ; call subroutine display-counter
warte: IN mp,TCNT0 ; read again timer 0
CPI mp,0 ; test for zero
BREQ warte ; wait until not zero any more
RJMP loop ; goto next round

IncZ1: INC z1 ; Increment software-counter


RET ; return to the main program

Display:
MOV mp,z1 ; copy counter value to mp
COM mp ; One-complement = XOR(FF) due to the LEDs drivers
OUT PORTB,mp ; write to LED port
RET ; Back to Main program

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TEST3.html1/20/2009 7:56:15 PM
http://www.avr-asm-tutorial.net/avr_en/source/TEST3.asm

; Test 3: Learning even more about the board: timer in polling mode
; New things to learn:
; - Timer in polling mode
; - MOV-command
; Again my special DEVICE-command
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; universal register definition
.DEF mp = R16
; Counter for the number of timeouts
.DEF z1 = R0
; Reset-Vector on adress 0000
rjmp main
; Main program starts here
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer (Subroutines!)
out SPL,mp
ldi mp,HIGH(RAMEND)
out SPH,mp
; Software-Counter-Register to zero
ldi mp,0 ; z1 cannot directly be set to zero as it is below R16
mov z1,mp ; So set mp to zero and copy to R0
; Prescaler of the timer = 1024, 4 MHz/1024 = 3906,25 Hz
; that equals a timer tick every 256 µs.
ldi mp,0x05 ;Initiate Timer/Counter 0 Prescaler
out TCCR0,mp ; to Timer 0 Control Register
; Port B is LED-port
ldi mp,0xFF ; all bits as output
out DDRB,mp ; to data direction register
; Main program loop reads the counter until he reaches zero, increments
; software counter and displays result on the LEDs.
; 256 timer ticks need 65.536 ms, resulting in a frequency of 15.25878906 Hz.
loop:
in mp,TCNT0 ; read the 8-bit timer 0
cpi mp,0 ; test for zero
brne loop ; if not zero branch to loop start
rcall IncZ1 ; call subroutine software-timer-increment
rcall Display ; call subroutine display-software-counter
warte:
in mp,TCNT0 ; again read timer 0
cpi mp,0 ; test for zero
breq warte ; wait until not zero any more
rjmp loop ; start next round
IncZ1:
inc z1 ; increment software counter
ret ; return to the main program
Display:
mov mp,z1 ; copy software counter to universal register
com mp ; One-complement = XOR(FF) due to reverse LEDs
out PORTB,mp ; send to LED port
ret ; return to the main program

http://www.avr-asm-tutorial.net/avr_en/source/TEST3.asm1/20/2009 7:56:17 PM
AVR-Tutorial, Part 4

PathHome => AVR-Overview => Tutorial => Part 4

; Test 4: Learn more about timer in interrupt


mode

; New things to learn here:


; - Timer in interrupt mode
; - Interrupts, Interrupt-Vector
; - BCD-Arithmetic

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; define universal register

.DEF mp = R16

; Counts the number of overflows of the hardware counter, called software counter

.DEF z1 = R0

; Working register for the Interrupt-Service-Routine

; Note that any registers used during an interrupt, including the


; status-register with all the flags, must either be
; reserved for that purpose or they have to reset to their initial
; value at the end of the service routine! Otherwise nice and
; nearly unpredictable effects will occur.

.DEF ri = R1

; Register zum Zählen der Sekunden, gepackte BCD-Ziffern

.DEF sec = R2

; Reset-Vektor on address 0000

RJMP main

; This is the first time we really need this RJMP command, because here
; we have to put interrupt vectors to position 1, 2, 3 and so on.
; Interrupt-vector definitions not used here (all but the timer overflow vector)
; are dummied by the return-from-interrupt command RETI,
; RETI is a special return command for interrupt service routines as it
; preserves the interrupt-flags in the status-register. Be sure that the jump
; to the interrupt service routine tc0i is exactly at adress 0007, otherwise
; the interrupt fails. The following mechanism goes on: If the timer overflows
; (transition from 255 to 0) the program run is interrupted, the current adress
; in the program counter is pushed to the stack, the command at adress 0007
; is executed (usually a jump instruction). After finishing execution of the
; interrupt service routine the program counter value is restored from the
; stack and program execution maintains at that point.

The interrupt-vector commands, 1 Byte each:

RETI ; Int0-Interrupt
RETI ; Int1-Interrupt
RETI ; TC1-Capture
RETI ; TC1-Compare A
RETI ; TC1-Compare B
RETI ; TC1-Overflow
RJMP tc0i ; Timer/Counter 0 Overflow, my jump to the service routine
RETI ; Serial Transfer complete
RETI ; UART Rx complete
RETI ; UART Data register empty
RETI ; UART Tx complete
RETI ; Analog Comparator

; Interrupt-Service-Routine for the counter

tc0i: IN ri,SREG ; save the content of the flag register


INC z1 ; increment the software counter
OUT SREG,ri ; restore the initial value of the flag register
RETI ; Return from interrupt

; ; The main program starts here

main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer


OUT SPL,mp ; for use with interrupts and subroutines
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Software-counter-register to zero
LDI mp,0 ; z1 cannot be accessed directly
MOV z1,mp ; copy 0 in mp to z1
MOV sec,mp ; and to the seconds counter

; Prescaler of the counter/timer = 256, that is 4 MHz/256 =


15625 Hz = $3D09
LDI mp,0x04 ;Initiate Timer/Counter 0 prescaler
OUT TCCR0,mp ; to Timer 0 Control register

; Port B is LED-port

LDI mp,0xFF ; all bits are output


OUT DDRB,mp ; to data direction register

; enable interrupts from timer 0


LDI mp,$02 ; Bit 1 set to 1
OUT TIMSK,mp ; in Timer Interupt Mask Register

; Enable all interrupts


SEI ; enables interrupts by setting flag in status-register

; The 8-bit counter overflows from time to time and the interrupt service
; routine increments a counter in a register. The main program loop reads this
; counter register and waits until it reaches hex 3D. Then the timer is read until
; he reaches 09 (one second = dez 15625 = hex 3D09 timer pulses). The timer
; and the register are set to zero and one second is incremented. The seconds
; are handled as packed BCD-digits (one digit = four bits, 1 Byte represents
; two digits). The seconds are reset to zero if 60 is reached. The seconds
; are displayed on the LEDs.

loop: LDI mp,$3D ; compare value for register counter


loop1: CP z1,mp ; compare with the register
BRLT loop1 ; z1 < mp, wait
loop2: IN mp,TCNT0 ; read counter LSB
CPI mp,$09 ; compare with LSB
BRLT loop2 ; TCNT0 < 09, wait
LDI mp,0 ; zero to
OUT TCNT0,mp ; hardware-counter LSB
MOV z1,mp ; and to software-counter MSB
RCALL IncSec ; subroutine increment second counter
RCALL Display ; display second counter
RJMP loop ; the same again

; subroutine for incrementing the second counter

; in BCD-arithmetic! Lower Nibble = Bit 0..3, Upper Nibble = 4..7

IncSec: SEC ; Set Carry-Flag for adding a one


LDI mp,6 ; Provoke overflow of lower Nibble
ADC sec,mp ; by adding 6 + 1 (Carry)
BRHS Chk60 ; if overflow then jump to 60-Check
SUB sec,mp ; subtract 6, no overflow occurred
Chk60: LDI mp,$60 ; compare with 60
CP sec,mp
BRLT SecRet ; jump, if lower than 60
LDI mp,256-$60 ; load complement
ADD sec,mp ; and add to zero
SecRet: RET ; return to the main program

; subroutine displaying the second counter on the LEDs

Display:
MOV mp,sec ; copy seconds to mp
COM mp ; One-complement = XOR(FF) to invert
OUT PORTB,mp ; software-counter to LEDs
RET ; Back to the main program

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TEST4.html1/20/2009 7:56:21 PM
http://www.avr-asm-tutorial.net/avr_en/source/TEST4.asm

; Test 4: Even more about the board: timer in interupt mode


; New things to learn here:
; - Timer in interrupt mode
; - Interrupts, Interrupt-vektor
; - BCD-arithmetic
; Here is my substitute for the DEVICE-command
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Universal register definition
.DEF mp = R16
; Counter for timer timeouts, MSB timer driven by software
.DEF z1 = R0
; Working register for the Interrupt-Service-Routine
; Note that any registers used during an interrupt, including the
; status-register with all the flags, must either be
; reserved for that purpose or they have to reset to their initial
; value at the end of the service routine! Otherwise nice and
; nearly unpredictable effects will occur.
.DEF ri = R1
; Register for counting the seconds as packed BCD
.DEF sec = R2
; Reset-vector to adress 0000
rjmp main
; This is the first time we really need this RJMP command, because here
; we have to put interrupt vectors to position 1, 2, 3 and so on.
; Interrupt-vector definitions not used here (all but the timer overflow vector)
; are dummied by the return-from-interrupt command RETI,
; RETI is a special return command for interrupt service routines as it
; preserves the interrupt-flags in the status-register. Be sure that the jump
; to the interrupt service routine tc0i is exactly at adress 0007, otherwise
; the interrupt fails. The following mechanism goes on: If the timer overflows
; (transition from 255 to 0) the program run is interrupted, the current adress
; in the program counter is pushed to the stack, the command at adress 0007
; is executed (usually a jump instruction). After finishing execution of the
; interrupt service routine the program counter value is restored from the
; stack and program execution maintains at that point.
; The interrupt-vector commands, 1 Byte each:
reti ; Int0-Interrupt
reti ; Int1-Interrupt
reti ; TC1-Capture
reti ; TC1-Compare A
reti ; TC1-Compare B
reti ; TC1-Overflow
rjmp tc0i ; Timer/Counter 0 Overflow, my jump-vector!
reti ; Serial Transfer complete
reti ; UART Rx complete
reti ; UART Data register empty
reti ; UART Tx complete
reti ; Analog Comparator
; Interrupt-Service-Routine for the counter
tc0i:
in ri,SREG ; save the content of the flag register
inc z1 ; increment the software counter
out SREG,ri ; restore the initial value of the flag register
reti ; Return from interrupt
; The main program starts here
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; for the use by interrupts and subroutines
ldi mp,HIGH(RAMEND)
out SPH,mp
; Software-Counter-Register reset to zero
ldi mp,0 ; z1 cannot be set to a constant value, so we set mp
mov z1,mp ; to zero and copy that to R0=z1
mov sec,mp ; and set the seconds to zero
; Prescaler of the counter/timer = 256, that is 4 MHz/256 = 15625 Hz = $3D09
ldi mp,0x04 ;Initiate Timer/Counter 0 Prescaler
out TCCR0,mp ; to Timer 0 Control Register
; Port B is LED-port
ldi mp,0xFF ; all bits are output
out DDRB,mp ; to data direction register
; enable interrupts for timer 0
ldi mp,$02 ; set Bit 1
out TIMSK,mp ; in the Timer Interupt Mask Register
; enable all interrupts generally
sei ; enable all interrupts by setting the flag in the status-register
; The 8-bit counter overflows from time to time and the interrupt service
; routine increments a counter in a register. The main program loop reads this
; counter register and waits until it reaches hex 3D. Then the timer is read until
; he reaches 09 (one second = dez 15625 = hex 3D09 timer pulses). The timer
; and the register are set to zero and one second is incremented. The seconds
; are handled as packed BCD-digits (one digit = four bits, 1 Byte represents
; two digits). The seconds are reset to zero if 60 is reached. The seconds
; are displayed on the LEDs.
loop:
ldi mp,$3D ; compare value for register counter
loop1:
cp z1,mp ; compare with the register
brlt loop1 ; z1 < mp, wait
loop2:
in mp,TCNT0 ; read LSB in the hardware counter
cpi mp,$09 ; compare with the target value
brlt loop2 ; TCNT0 < 09, wait
ldi mp,0 ; set register zero and ...
out TCNT0,mp ; reset hardware-counter LSB
mov z1,mp ; and software-counter MSB
rcall IncSec ; call the subroutine to increment the seconds
rcall Display ; call subroutine to display the seconds
rjmp loop ; once again the same
; subroutine increment second counter
; in BCD-arithmetic! Lower nibble = Bit 0..3, upper nibble = 4..7
IncSec:
sec ; Setze Carry-Flag for adding an additional one to the seconds
ldi mp,6 ; povoke overflow of the lower nibble by adding 6
adc sec,mp ; add 6 + 1 (Carry)
brhs Chk60 ; if overflow of the lower nibble occurred go to 60 check
sub sec,mp ; subtract the additional 6 as no overflow occurred
Chk60:
ldi mp,$60 ; 60 seconds already reached?
cp sec,mp
brlt SecRet ; jump if less than 60
ldi mp,256-$60 ; Load mp to add sec to zero
add sec,mp ; Add mp to reset sec to zero
SecRet:
ret ; return to the main program loop
; subrountine for displaying the sonds on the LEDs
Display:
mov mp,sec ; copy seconds to mp
com mp ; One-complement = XOR(FF) to invert the bits
out PORTB,mp ; send to the LED port
ret ; return to main program loop

http://www.avr-asm-tutorial.net/avr_en/source/TEST4.asm1/20/2009 7:56:26 PM
AVR-Hardware-Testroutines

Path: Home => AVR-Overview => Hardware

Tutorial for learning the assembly


language of
AVR-Single-Chip-Processor
AT90Sxxxx
of ATMEL by programming examples.
Hardware on the STK board

(Click the links on the *.asm-files together with the shift key, if you want to download them.)
HTML- ASM-
Comments
Format Format
Read and Write the EEPROM. During programming the chip a counter value
in the EEPROM is set to zero. During every restart of the board hardware this
counter value is read, increased, written back to the EEPROM and its value is
EEPROM EEPROM
displayed on the eight LEDS of the board. Please note that error messages
during verification after programming of the chip will occur and read the
hints at the end of the program file.
Tests external RAM on board of the STK-200. Counts RAM-positions by
writing hex AA und 55 in the RAM positions, verifies their content and
RAM RAM
displays the the MSB of the last RAM adress found ok on the LEDs of the
board.
Clears the LCD-Display and writes a test-text to line 1 and 2 of the LCD
LCD LCD display. Die required LCD-basic-routines are written in a separate Include-
file, so you can use this include-file for your own purposes.
Sends a message text on the serial interface with 9k6 8N1 and then echoes
SIO SIO incoming characters. For the setup of the hardware and the terminal program
see the file TESTSIO.txt!
Similiar: Receives characters over the serial interface with 9k6 8N1 and
SIO SIO echoes their hexadecimal codes back. Hardware and terminal program hints
are also found at this link!
Back to the AVR index

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_HARD.html1/20/2009 7:56:28 PM
AVR-Hardware-Tutorial, <A HREF="beginner/PDETAIL.html#EEPROM">EEPROM</A>-Test

Path: Home => AVR-Overview => Hardware => EEPROM

; Demonstrates the use of the EEPROM


;
; During programming a counter location, defined in the EEPROM,
; is set to zero. At every restart of the processor this counter is incremented
; and its content is displayed in hex format on the LEDs.
; Please refer to the hints given on the end of this code to avoid
; some confusion.
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Define constants
;
.equ cnt=$0000 ; Adress of the counter location in the EEPROM
;

; Define registers
.def mpr=R16 ; Universal register
.def neu=R17 ; Counter value interim storage
;

; Reset-/Interrupt-Vector

RJMP main ; Jump to main program


;
main:
LDI mpr,$FF ; all bits of Port B are output
OUT DDRB,mpr

; Program reads a byte in the EEPROM

LDI mpr,LOW(cnt) ; Set EEPROM adress


OUT EEARL,mpr ; to the EEPROM-adress port
LDI mpr,HIGH(cnt) ; Low/High-Byte separate
OUT EEARH,mpr ; EEPROM has 512 Byte locations
SBI EECR,EERE ; Set Read-Enable-Bit EERE
; in EEPROM-Control-Register EECR
IN neu,EEDR ; Read byte from EPROM-location
; Increment counter and write back to EEPROM
INC neu
wart:

; If EEPROM busy, wait first

SBIC EECR,1 ; Busy Bit 1 in EEPROM-Control-Register


RJMP wart ; not ready, wait
; The EEPROM-Adress is still correct, so we don't need to adjust it
; We just transfer the new data to the EEPROM-data register
OUT EEDR,neu ; New value to EEPROM-Data register
; The following two write commands must not be interrupted, because safe write operations
; are only valid if these come within four commands. Otherwise hardware skips the write operation.
; Interrupts must be disabled therefore (interrupts are not used here).
CLI

; Now the two write commands:

SBI EECR,EEMWE ; Switches EEPROM Master Write Enable on


SBI EECR,EEWE ; Enables write operation in the EEPROM
; Within the following 1,5 milliseconds the byte is written to the EEPROM location.
; This is sensitive only in case you want to use the EEPROM for further operations.
; Not here: We write the inverted content of the counter to the LEDs on Port B
; and end the program in an indefinit loop.
COM neu ; invert
OUT PORTB,neu ; to Port B
loop: RJMP loop ; wait forever.

; Here starts the setting of the counter to zero during


programming
; First we have to tell the assembler that the following code goes to the EEPROM segment
; and not to the code segment:
.ESEG

; Now the content of the EEPROM-segment:

.DB $00 ; A Byte with a zero


; That's it.

; IMPORTANT HINTS
; During programming the content of the EEPROM-file TESTEEP.EEP
; will be loaded separately and programmed after the code is loaded.
; Don't forget this!
; During the programming sequence of the different locations for code
; and EEPROM content the software for the board releases the Reset pin
; of the processor, e.g. between programming and verification. As this
; short pause already causes the processor to restart and execute the
; code. Verification of the EEPROM content will therefore fail, because
; the counter is already incremented and does not match its original
; programmed value. Every read operation of the EEPROM content
; onboard will have the same effect.
; The execution of the restart command using the ISP software also
; causes multiple startups of the processor and increases the counter
; value, so don't expect to see correct counting values.
; Exact up-counts are only seen when switching the supply voltage
; of the board off and on.
; To avoid unwanted upcounting during program, verification and read
; operation would require setting a startup delay time, but this is a
; little bit too complex for a beginner.

Back to the Hardware page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTEEP.html1/20/2009 7:56:32 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTEEP.asm

; Demonstates the use of the EEPROMs


;
; During the programming a counter location, defined in the EEPROM,
; is set to zero. At every restart of the processor this counter is incremented
; and its content is displayed in hex format on the LEDs.
; Please refer to the hints given on the end of this code to avoid confusion!
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Define constants
;
.equ cnt=$0000 ; Adress of the counter location in the EEPROM
;
; Define registers
.def mpr=R16 ; Universal register
.def neu=R17 ; Counter value interim storage
;
; Reset-/Interrupt-Vector
rjmp main ; Jump to main program
;
main:
ldi mpr,$FF ; all bits of Port B are Output
out DDRB,mpr
; Program reads a byte from the EEPROM location
ldi mpr,LOW(cnt) ; Set the EEPROM location to read from
out EEARL,mpr ; tell this to EEPROM-Port
ldi mpr,HIGH(cnt) ; Low/High-Byte will be read separately
out EEARH,mpr ; as there are 512 byte locations available
sbi EECR,EERE ; Set the Read-Enable-Bit EERE in the
; EEPROM-Control-Register EECR
in neu,EEDR ; Read the byte from the EEPROM-location
; Increment the counter and write back to the same EEPROM location
inc neu
wart:
; If EEPROM is not ready, wait first
sbic EECR,1 ; Read bit 1 in the EEPROM-Control-Register
rjmp wart ; and repeat until EEPROM reports ready
; The EEPROM-adress location isn't changed, so we don't need to set that first
; by transfer of the EEPROM-write adress to EEARL/EEARH
out EEDR,neu ; New counter value to the EEPROM-data register
; The two write commands must not be interrupted, because they must be executed
; within four commands to ensure prevention of any unwanted write commands to
; the EEPROM. So we have to disable any interrupts before entering the write
; sequence.
cli ; disables all interrupts
; Now we can start the two write commands:
sbi EECR,EEMWE ; Switches on the EEPROM Master Write Enable
sbi EECR,EEWE ; Starts the write command to the EEPROM
; During the following ca. 1,5 milliseconds the byte is written to the EEPROM.
; This affects us only if we want to use the EEPROM for further operations.
; Not here: we write the inverted content of the counter to the Port B, the
; LED-port, and end the program with a indefinite loop.
com neu ; invert the counter (XOR FFh)
out PORTB,neu ; to Port B
loop:
rjmp loop ; wait undefinitely
; Here we start defining the initial value of the counter location in the EEPROM
; during programming.
; First we tell the assembler, that the following informations go to the EEPROM.
.ESEG
; Now we define the EEPROM-content:
.DB $00 ; One byte with a zero
; That's about it.
; IMPORTANT HINTS
; During programming the content of the EEPROM-file TESTEEP.EEP
; will be loaded separately and programmed after the code is loaded.
; Don't forget this!
; During the programming sequence of the different locations for code
; and EEPROM content the software for the board releases the Reset pin
; of the processor, e.g. between programming and verification. As this
; short pause already causes the processor to restart and execute the
; code. Verification of the EEPROM content will therefore fail, because
; the counter is already incremented and does not match its original
; programmed value. Every read operation of the EEPROM content
; onboard will have the same effect.
; The execution of the restart command using the ISP software also
; causes multiple startups of the processor and increases the counter
; value, so don't expect to see correct counting values.
; Exact up-counts are only seen when switching the supply voltage
; of the board off and on.
; To avoid unwanted upcounting during program, verification and read
; operation would require setting a startup delay time, but this is a
; little bit too complex for a beginner.

http://www.avr-asm-tutorial.net/avr_en/source/TESTEEP.asm1/20/2009 7:56:36 PM
AVR-Hardware, test external <A HREF="beginner/SRAM.html#top">SRAM</A>

Path: Home => AVR-Overview => Hardware => RAM

; TestRam tests external SRAM on the STK-200


board
; ************************************************
; TestRam tests external SRAM on the STK200 board
; Counts SRAM-positions by writing AAh and 55h
; in each position, verifies the content and displays
; the MSB of the highest SRAM-adress on the LEDs.
; ************************************************

; Explanation on the RAM access


; The MUX-IC 74HC573 and the SRAM 62256-70 have to be
; installed on the board.
; Port A is multiplexed adress bus for the LSB adress and the
; data bus
; Port C is the upper adress bus
; Port D Bit 6 is /RD (Read) on the SRAM, Bit 7 is /WR (Write)
; Line ALE (Adress Latch Enable) is used, Pin 30 of the 8515
; If the whole external SRAM has been tested ok, all LEDs are
; switched on except LED7. The highest adress then is
; 7FFFh, if a 32 kB SRAM is used.

; 8515-definitions

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Registers
.def mp = R16 ; Multi-Purpose
.def soll = R17 ; AA or 55 for test

; Reset-/Interrupt-Vector

RJMP main

; Main program
main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer
OUT SPL,mp ; for subroutines
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Port B drives the LEDs

LDI mp,0xFF ; All outputs


OUT DDRB,mp ; to data direction register

IN mp,MCUCR ; Read MCU-Control-Register


ORI mp,0x80 ; Set Bit 7
OUT MCUCR,mp
; If the SRAM used is slower than 70 ns and therefore requires an
; additional WAIT-state, then Bit 6 has to set additionally. The
; ORI command then must be ORI mp,0xC0 to set bit 6, too.

LDI XL,LOW(RAMEND) ; Register XL is R26, LSB RAM-Adress


LDI XH,HIGH(RAMEND) ; Register XH is R27, MSB RAM-Adress

LDI soll,0b10101010 ; Bit pattern for Test

loop:
INC XL ; Inc adress
BRNE check ; Not zero, MSB ok
INC XH ; Inc MSB of Adress
BREQ check ; Zero, MSB overflow, skip
check:
ST X,soll ; write Bitpattern to SRAM
LD mp,X ; Read the same location
CP mp,soll ; Compare written and read
BRNE Zurueck ; Not equal, skip
COM soll ; Invert bit pattern (XOR FF)
ST X,soll ; write 0101.0101
LD mp,X ; Read back
CP mp,soll ; compare
BRNE Zurueck ; Not equal, skip
COM soll ; invert
RJMP loop ; next location

Zurueck:
LD mp,-X ; Decrement Pointer X
Ungleich:
COM XH ; XOR FF of MSB
OUT PORTB,XH ; to the LEDs
ende: RJMP ende ; Loop forever

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTRAM.html1/20/2009 7:56:39 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTRAM.asm

; ************************************************
; TestRam tests external SRAM on the STK200 board
; Counts SRAM-positions by writing AAh and 55h
; in each position, verifies the content and displays
; the MSB of the highest SRAM-adress on the LEDs.
; ************************************************
; Explanation on the RAM access
; The MUX-IC 74HC573 and the SRAM 62256-70 have to be
; installed on the board.
; Port A is multiplexed adress bus for the LSB adress and the
; data bus
; Port C is the upper adress bus
; Port D Bit 6 is /RD (Read) on the SRAM, Bit 7 is /WR (Write)
; Line ALE (Adress Latch Enable) is used, Pin 30 of the 8515
; If the whole external SRAM has been tested ok, all LEDs are
; switched on except LED7. The highest adress then is
; 7FFFh, if a 32 kB SRAM is used.
; 8515-definitions
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Registers
.def mp = R16 ; Multi-Purpose
.def soll = R17 ; AA and 55
; Reset-/Interrupt-Vector
rjmp main
; Main program
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; for the use with subroutines
ldi mp,HIGH(RAMEND)
out SPH,mp
; Port B is driver for the LEDs
ldi mp,0xFF ; All outputs
out DDRB,mp ; to data direction register Port B
in mp,MCUCR ; Read MCU-Control-Register
ori mp,0x80 ; Set Bit 7
out MCUCR,mp
; If the SRAM used is slower than 70 ns and therefore requires an
; additional WAIT-state, then Bit 6 has to set additionally. The
; ORI command then must be ORI mp,0xC0 to set bit 6, too.
ldi XL,LOW(RAMEND) ; Register XL is R26, LSB RAM-Adress
ldi XH,HIGH(RAMEND) ; Register XH is R27, MSB RAM-Adress
ldi soll,0b10101010 ; Bit pattern AAh for test
loop:
inc XL ; Increment 16-bit adress counter by 1
brne check ; No carry to MSB
inc XH ; Increment MSB
breq check ; MSB overroll, end
check:
st X,soll ; write Bit pattern to SRAM
ld mp,X ; Read the same SRAM-Adress
cp mp,soll ; compare written and read
brne Zurueck ; Not equal, skip further tests
com soll ; Invert bit pattern (XOR FF)
st X,soll ; Test again with 0101.0101=55h
ld mp,X ; Read
cp mp,soll ; Compare
brne Zurueck ; Not equal, skip further testing
com soll ; invert test pattern again
rjmp loop ; Go on with next location
Zurueck:
ld mp,-X ; Drecrement Pointer X, Result in mp doesn't matter
Ungleich:
com XH ; XOR FF of the highest RAM-Adress
out PORTB,XH ; to the LEDs
ende:
rjmp ende ; Loop for ever

http://www.avr-asm-tutorial.net/avr_en/source/TESTRAM.asm1/20/2009 7:56:40 PM
AVR-Hardware, LCD-display test

Path: Home => AVR-Übersicht => Hardware => LCD

; ************************************************

; TestLcd clears the LCD-Display and displays a


text on the LCD.
; ************************************************

; Basics of the LCD operation on the STK200 boad


; Hardware: The 2-line-LCD-Display must be mounted

;
; on the board and connected correctly. It is recommended
; to connect a 14-pin female connector to the backside
; of the LCD display board that fits the male connector

;
; on the STK200. That's all for the hardware, all other

;
; hardware is already on board of the STK200 (lousy
; documentation of this!).
; Software: The access to the LCD is in this case programmed
; in memory-mapped mode, not via I/O commands. This
; has the advantage that the same commands of the RAM
; access can be used, complicated port bits programming
; is avoided and external 32 kB memory can be used in
; parallel. (Example programs for LCD access found in the
; internet are all I/O-mapped and do not run correct with
; the 32 kB memory on board the STK200 in parallel.
; The adress for LCD access is $8000 for commands and
; $C000 for access to the charcater generator and the
; display lines (both read and write).
; As memory-mapped access is too fast for most LCDs
; the WAIT-Bit in the MCUCR register has to be set to insert
; a wait state. This slows down the RAM access, too, but
; should not be a problem in most cases. To speed-up
; RAM access the WAIT-bit could be set to zero during
; times where only RAM access is made and set to 1 again
; when access to the LCD follows.
; Used Ports: The following ports are used, both by LCD and RAM
; access:
; Port A: Alternate use as LSB adress bus and data bus; not
; used during LCD access, but blocked by memory-
; mapped access
; Port C: MSB adress bus for SRAM access; used for LCD
; access: Bit 7 (Adress signal) and 6 (RS signal of
; the LCD)
; Port D: Bit 6 is /RD (Read) on the SRAM, not used by LCD
; access, Bit 7 is /WR (Write) on the SRAM and on the
; LCD
;
; Test program sequence: Sequentially the following steps are
; executed:
; 0. Wait until the LCD is not busy any more
; 1. Clear the LCD
; 2. Set the transfer mode to 8-bit, a fixed display window and
; define other display properties
; 3. Output to lines of text on the LCD window
; Before each operation takes place a LED is switched on
; to allow debugging the single steps. If all steps are executed
; correct LED 4 is on and the text on the LCD is visible
; (if not visible: correct contrast setting of the LCD).
;
; Structure of the software: All LCD operations are programmed as
; subroutines and so can be exported and used in other programs
; easily. Used registers are: mp=Allround register for handing
; values to subroutines; R26/27=XL/XH is a 16-bit-adress
; for SRAM/LCD-access commands ST X and LD X
;

; Load 8515-library

.NOLIST
.INCLUDE "8515def.inc"
.LIST

; Registers
.def mp = R16 ; Multi-Purpose
.def test = R17 ; Counts the test phases for debugging

; Reset-/Interrupt-Vector

RJMP main

; Subroutines for LCD access


LcdWt: ; Wait until the LCD-Busy-Flag is zero
LDI XH,0x80 ; Upper byte of RAM adress of LCD
LDI XL,0x00 ; Lower Byte of RAM-Adresse of LCD
LD mp,X ; Read Busy flag und AC-Adress
ROL mp ; Shift Bit 7 to carry flag
BRCS LcdWt ; If one, then busy, repeat
RET

LcdCl: ; Clear the LCD


LDI mp,0x01 ; Clear command is 01h

LcdBef: ; Command byte in mp to LCD, if it is ready


PUSH mp ; Command in mp to stack
RCALL LcdWt ; Wait until LCD is not busy
POP mp ; Pop command from stack
ST X,mp ; Command to LCD
RET ; End of subroutine

LcdInit: ; Init mode of LCD


LDI mp,0b00111000 ; 8-Bit-Transfer, not four bit
RCALL LcdBef ; command to LCD
LDI mp,0b00000110 ; Increment, Display freeze
RCALL LcdBef ; command to LCD
LDI mp,0b00010000 ; Cursor move, not shift
RCALL LcdBef ; command to LCD
RET ; Back

LcdBu: ; Write character in mp to LCD


PUSH mp ; Save character on stack
RCALL LcdWt ; Wait until not busy
POP mp ; Restore character
LDI XH,0xC0 ; Storage of LCD on adress 0C00h
ST X,mp ; Write character to LCD
RET ; Back

LcdTs: ; Write the word "Test" to the current line


PUSH mp ; Save the line adress in mp
RCALL LcdWt ; Wait for not busy
POP mp ; Line adress to mp
ORI mp,0x80 ; Set Bit 7 of line adress
RCALL LcdBef ; Command to LCD
LDI mp,'T' ; Letter T
RCALL LcdBu ; Write to LCD
LDI mp,'e' ; Letter e
RCALL LcdBu ; Write to LCD
LDI mp,'s' ; Letter s
RCALL LcdBu ; Write to LCD
LDI mp,'t' ; Letter t
RCALL LcdBu ; Write to LCD
RET ; Ready, Back

LcdTst: ; Write the word "Test" to line 1 and 2


LDI mp,0x00 ; Line 1 starts at adress 00h
RCALL LcdTs ; Write to line 1
LDI mp,0x40 ; Line 2 starts at adress 40h
RCALL LcdTs ; Write to line 2
LDI mp,0b00001111 ; Command Display On, Cursor On und Blink
RCALL LcdBef ; Command to LCD
RET ; Back

; Main program
main: LDI mp,LOW(RAMEND) ;Initiate Stackpointer
OUT SPL,mp ; for subroutine use
LDI mp,HIGH(RAMEND)
OUT SPH,mp

; Port B outputs to the LEDs

LDI mp,0xFF ; All output


OUT DDRB,mp ; to Data Direction

IN mp,MCUCR ; Read MCU-Control-Register


ORI mp,0xC0 ; Set Bit 7 (SRAM) and Bit 6 (WAIT-STATE)
OUT MCUCR,mp

; Here starts the test of the LCD


LDI test,0xFE ; Set Bit 0 to 0 = LED 0 on
OUT PORTB,test ; LED 0 on
RCALL LcdWt ; Wait on busy
;if error, stops here with LED 0 on

SEC ; Set Carry Flag


ROL test ; Shift one left = LED 1 on
OUT PORTB,test
RCALL LcdCl ; Clear LCD

SEC ; Carry to 1
ROL test ; Shift left for LED 2 on
OUT PORTB,test
RCALL LcdInit ; Init LCD

SEC ; Set Carry Flag


ROL test ; Shift left for LED 3 on
OUT PORTB,test
RCALL LcdTst ; Write the test lines

SEC ; Carry on
ROL test ; Shift left to LED 4 on
OUT PORTB,test

ende: RJMP ende ; Loop forever

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTLCD.html1/20/2009 7:56:46 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTLCD.asm

; ************************************************
; TestLcd clears the LCD-Display and outputs
; a test text in line 1 and 2 of the display
; ************************************************
; Basics of the LCD operation on the STK200 boad
; Hardware: The 2-line-LCD-Display must be mounted
; on the board and connected correctly. It is recommended
; to connect a 14-pin female connector to the backside
; of the LCD display board that fits the male connector
; on the STK200. That's all for the hardware, all other
; hardware is already on board of the STK200 (lousy
; documentation of this!).
; Software: The access to the LCD is in this case programmed
; in memory-mapped mode, not via I/O commands. This
; has the advantage that the same commands of the RAM
; access can be used, complicated port bits programming
; is avoided and external 32 kB memory can be used in
; parallel. (Example programs for LCD access found in the
; internet are all I/O-mapped and do not run correct with
; the 32 kB memory on board the STK200 in parallel.
; The adress for LCD access is $8000 for commands and
; $C000 for access to the charcater generator and the
; display lines (both read and write).
; As memory-mapped access is too fast for most LCDs
; the WAIT-Bit in the MCUCR register has to be set to insert
; a wait state. This slows down the RAM access, too, but
; should not be a problem in most cases. To speed-up
; RAM access the WAIT-bit could be set to zero during
; times where only RAM access is made and set to 1 again
; when access to the LCD follows.
; Used Ports: The following ports are used, both by LCD and RAM
; access:
; Port A: Alternate use as LSB adress bus and data bus; not
; used during LCD access, but blocked by memory-
; mapped access
; Port C: MSB adress bus for SRAM access; used for LCD
; access: Bit 7 (Adress signal) and 6 (RS signal of
; the LCD)
; Port D: Bit 6 is /RD (Read) on the SRAM, not used by LCD
; access, Bit 7 is /WR (Write) on the SRAM and on the
; LCD
;
; Test program sequence: Sequentially the following steps are
; executed:
; 0. Wait until the LCD is not busy any more
; 1. Clear the LCD
; 2. Set the transfer mode to 8-bit, a fixed display window and
; define other display properties
; 3. Output to lines of text on the LCD window
; Before each operation takes place a LED is switched on
; to allow debugging the single steps. If all steps are executed
; correct LED 4 is on and the text on the LCD is visible
; (if not visible: correct contrast setting of the LCD).
;
; Structure of the software: All LCD operations are programmed as
; subroutines and so can be exported and used in other programs
; easily. Used registers are: mp=Allround register for handing
; values to subroutines; R26/27=XL/XH is a 16-bit-adress
; for SRAM/LCD-access commands ST X and LD X
;
;
; 8515-definitions load
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
; Registers
.def mp = R16 ; Multi-Purpose
.def test = R17 ; Counts the different test phases
; Reset-/Interrupt-Vector
rjmp main
; Subroutines for memory-mapped LCD access
LcdWt:
; Wait until the LCD-busy-flag is zero
ldi XH,0x80 ; Upper Byte of the RAM adress of the LCD
ldi XL,0x00 ; Lower Byte of the RAM adress of the LCD
ld mp,X ; Read busy flag and AC-Adress
rol mp ; Shift bit 7 of the LCD status to the carry flag
brcs LcdWt ; If one then LCD is still busy, repeat
ret
LcdCl:
; Clear the LCD
ldi mp,0x01 ; Clear command of the LCD display = 01h
LcdBef:
; LCD command in register mp to LCD, if ready
push mp ; Command byte in mp is used later, save on stack
rcall LcdWt ; Wait until display is not busy any more
pop mp ; Recall command byte from stack
st X,mp ; Send command to LCD
ret ; End of the subroutine
LcdInit:
; Init mode of the LCD
ldi mp,0b00111000 ; 8-Bit-mode, not 4-Bit-mode
rcall LcdBef ; command byte to the LCD
ldi mp,0b00000110 ; Increment, display freeze
rcall LcdBef ; commad byte to the LCD
ldi mp,0b00010000 ; Cursor move, not shift
rcall LcdBef ; command byte to the LCD
ret ; Return from subroutine
LcdBu:
; Write character in register mp on the LCD
push mp ; Character used later, save on stack
rcall LcdWt ; Wait until LCD is ready to receive
pop mp ; Pop character from stack
ldi XH,0xC0 ; LCD adress to register pair X
st X,mp ; Write character to LCD
ret ; Return from subroutine
LcdTs:
; Write the word "Test" to the current LCD display line
push mp ; Save the line adress in mp
rcall LcdWt ; Wait until the LCD is ready
pop mp ; Pop line Adress
ori mp,0x80 ; Set bit 7 of the line adress
rcall LcdBef ; and send to LCD
ldi mp,'T' ; Load character T
rcall LcdBu ; Write character to the LCD
ldi mp,'e' ; Load character e
rcall LcdBu ; Write to LCD
ldi mp,'s' ; Load charcater s
rcall LcdBu ; Write to LCD
ldi mp,'t' ; Load character t
rcall LcdBu ; Write to LCD
ret ; Ready, return back
LcdTst:
; Write "Test" to line 1 and 2 of the display
ldi mp,0x00 ; Line 1 starts at adress 00h of the display
rcall LcdTs ; Write test to line 1
ldi mp,0x40 ; Line 2 starts at adress 40h of the display
rcall LcdTs ; Write test to line 2
ldi mp,0b00001111 ; Command for display On, Cursor On and Blink
rcall LcdBef ; Command byte to LCD
ret ; Return from subroutine
; Main program
main:
ldi mp,LOW(RAMEND) ;Initiate Stackpointer
out SPL,mp ; for the use with subroutines
ldi mp,HIGH(RAMEND)
out SPH,mp
; Port B is the LED driver
ldi mp,0xFF ; All outputs
out DDRB,mp ; to data direction register of port B
in mp,MCUCR ; Read MCU-Control-Register
ori mp,0xC0 ; Set Bit 7 (SRAM) and Bit 6 (WAIT-STATE)
out MCUCR,mp
; Here the test of the LCD starts
ldi test,0xFE ; Set Bit 0 to 0 = LED 0 on
out PORTB,test ; LED 0 on
rcall LcdWt ; Wait until LCD isn't busy any more
; if an error happens here, the LED 0 won't go off
sec ; Set Carry Flag to 1
rol test ; Shift the zero in test one position left to switch LED 1 on
out PORTB,test
rcall LcdCl ; Clear the LCD
sec ; Set Carry flag to 1
rol test ; and shift test again one position left to switch LED 2 on
out PORTB,test
rcall LcdInit ; Some intiialisation of the LCD
sec ; Set Carry Flag again to 1
rol test ; and shift test left to switch LED 3 on
out PORTB,test
rcall LcdTst ; Write the testlines
sec ; Set Carry flag again to 1
rol test ; and shift test to set LED 4 on
out PORTB,test; Test is successfuly completed
ende:
rjmp ende ; Loop for always

http://www.avr-asm-tutorial.net/avr_en/source/TESTLCD.asm1/20/2009 7:56:47 PM
AVR-Hardware-Tutorial: SIO use

Path: Home => AVR-Overview => Hardware => SIO

; Tests the Serial Communication Port


;
; Sends a text over the serial communication port of an AVR with
; 9k6 8N1 and echoes incoming characters on the SIO port of an AVR.
;

; Hardware: Connection between the serial interfaces


; Windows serial communication with HyperTerminal (see text)
; or equivalent terminal program with ANSI ;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Constants
;
.EQU fq=4000000 ; Xtal frequency
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Divider
;

; Registers
;
.DEF mpr=R16 ; Universal register
.DEF nc=R17 ; Counter
.DEF c=R18 ; character
;

;Reset-/Interrupt-Vector

RJMP main
;
main: LDI mpr,bdteiler ; Baudgenerator
OUT UBRR,mpr ; Divider set
LDI mpr,0b00011000 ; Enable TX and RX
OUT UCR,mpr ; to UART Control Register
;

; Send all capital letters


;
LDI c,'A' ; first letter
LDI nc,90-65+1 ; number of letters
tloop: SBIS USR,UDRE ; Jump if transmit buffer empty
RJMP tloop ; Wait a bit
OUT UDR,c ; Letter to transmit buffer
INC c ; next letter
DEC nc ; Count letters to send
BRNE tloop ; next letter
;

; Wait until character comes in, echo back forever

;
rloop: SBIS USR,RXC ; Test RXC-bit for waiting char
RJMP rloop ; no character available
IN c,UDR ; Read char from UART
rwait: SBIS USR,UDRE ; Wait until TX ready
RJMP rwait ; TX not ready yet
OUT UDR,c ; Send char
CPI c,0x0D ; Return-char?
BRNE rloop ; No Return, go on
LDI c,0x0A ; Load Linefeed
RJMP rwait ; Send additional Linefeed

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTSIO.html1/20/2009 7:56:50 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTSIO.asm

; Test of the serial interface


;
; Sends a text on the serial interface using 9k6 8N1 and
; then echoes incoming charcaters
;
; Hardware: Connection between STK200 board an computer
; Windows-communication program HyperTerminal (see text)
; or equivalent terminal program with ANSI
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Constants
;
.EQU fq=4000000 ; XTal frequency
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Divider
;
; Registers
;
.DEF mpr=R16 ; Universal register
.DEF nc=R17 ; Counter
.DEF c=R18 ; Character
;
;Reset-/Interrupt-Vector
rjmp main
;
main:
ldi mpr,bdteiler ; Baudgenerator
out UBRR,mpr ; Set divider
ldi mpr,0b00011000 ; Enable TX and RX
out UCR,mpr ; to UART Control Register
;
; Send all Upcase characters
;
ldi c,'A' ; first character
ldi nc,90-65+1 ; Number of characters
tloop:
sbis USR,UDRE ; Jump if send buffer empty
rjmp tloop ; Wait a bit
out UDR,c ; Character to send buffer
inc c ; next character
dec nc ; Counter decrement
brne tloop ; next character
;
; Wait until character received and echo forever
;
rloop:
sbis USR,RXC ; Test RXC-bit for waiting characters
rjmp rloop ; None available, wait
in c,UDR ; Get character from UART
rwait:
sbis USR,UDRE ; Wait until transmit buffer empty
rjmp rwait ; Transmitter busy
out UDR,c ; Send character
cpi c,0x0D ; Return-character?
brne rloop ; No Return, go on
ldi c,0x0A ; Laad Linefeed
rjmp rwait ; Send additional Linefeed

http://www.avr-asm-tutorial.net/avr_en/source/TESTSIO.asm1/20/2009 7:56:52 PM
http://www.avr-asm-tutorial.net/avr_en/TESTSIO.txt

Hard- and Software for the communication of the STK-200 via the SIO/UART
=========================================================================

1. Hardware

Required is a 9 pin male plug for the STK200-board connection and either a
25-pin female or an additional 9-pin plug for the computer's serial interface.
The following three pins have to be connected within a 9-pin or a 25-pin
connector to ensure proper signal levels for the board and the computer:

9-pin: 25-pin: Name of the line


----------------------------------------------
Pin 4 = Pin 20 = Data Terminal Ready DTR
Pin 8 = Pin 5 = Clear To Send CTS
Pin 6 = Pin 6 = Data Set Ready DSR

The following pins of the connectors have to be connected with a cable:

9-pin: 25-pin: Name of the line


----------------------------------------------
Pin 2 = Pin 3 = Read Data RD
Pin 3 = Pin 2 = Transmit Data TD
Pin 5 = Pin 7 = Signal Ground SG

That's it all for the hardware part.

2. Software

Basically every terminal program is applicable for communication. Common


in the Windows world is HyperTerminal, as it is supplied with Win32. The
installation
is as follows:
a) In the Start-menu select PROGRAMS-HYPERTERMINAL.
b) In the open folder select HYPERTRM.EXE.
c) Select a name for the connection, e.g. STK200Sio and click Ok.
d) In the call-window leave the number empty. Open the selection box
CONNECT_VIA and select DIRECTCONNECTION_VIA_COMX.
(X is usually COM2, if your mause is connected to COM1.) Select Ok.
e) In the PROPERTIES-window select a baudrate of 9600 bps, 8 databits, no
parity, 1 stopbit and protocol HARDWARE.
f) In the white HyterTerminal-window you can communicate with the STK200 now.
After switching the STK200 board on it sends an identification string,
then echoes back all all characters you send to the board. For a real
hard test send a ASCII text file to the board (TRANSMIT-TEXTFILE)
g) By closing the Hyperterminal window answer the dialog with YES.
Answering the following question, if the session should be stored, also
with YES and you can use the same terminal properties when you connect
the next time to your STK200 board. To open the next session you can
simply click on the proper icon in the HyperTerminal folder.

3. Experiences with HyperTerminal

At baudrates above 19200 no proper connection is possible.

Non-US-ASCII characters are not properly handled. That's Windows.

At the beginning of a line one char is lost, if you transfer a text file.
This is due to the addition of a linefeed char after the STK200 has received
a carriage return. There is not enough time to echo the next char then.

(C)2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTSIO.txt1/20/2009 7:56:53 PM
SIOHEX echoes <A HREF="calc/CONVERSION.html#hex2bin">hex</A> codes of received characters on a STK200 board

Path: Home => AVR-Overview => Hardware => SIO hex

;
; Test of the Serial IO
;
; Receives charactern from the SIO with 9k6 8N1 and sends back
; their hex values as text
;
; Hardware: Serial connection between the board and a terminal
; Communication: Terminal program, e.g. HyperTerminal
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU fq=4000000 ; XTal-frequency
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Divider
.EQU RamStart = 0x0060
;
; Register
;
.DEF mpr=R16 ; Universal register
.DEF cc=R17 ; Char copy
.DEF h=R18 ; Various values
;
; XL/XH = R26/R27 are used as Pointer to the SRAM (input buffer
position)
; YL/YH = R28/R29 are used as Pointer to the SRAM (output buffer
position)
;
; Program code starts here
;
.CSEG
;
; Reset-Vector
;
RJMP main ; Reset-vector
;
main:
LDI XH,HIGH(RamStart)
LDI XL,LOW(RamStart)
LDI YH,HIGH(RamStart)
LDI YL,LOW(RamStart)
LDI mpr,0x0D ; Start with a new line
ST X+,mpr ; put to the SRAM buffer and inc input pointer
LDI mpr,0x0A ; additional linefeed
ST X+,mpr
LDI mpr,bdteiler ; Set baudrate generator
OUT UBRR,mpr ; to divider port
LDI mpr,0b00011000 ; Enable TX and RX
OUT UCR,mpr ; to UART Control Register
;
; Main program loop asks UART for characters and transmits buffered
chars in SRAM
;
tloop:
SBIC USR,RXC ; Jump if receiver is empty
RJMP rx ; Receive the next char
SBIC USR,UDRE ; Jump if the transmitter is not ready to
receive chars
RJMP tx ; Send next char
RJMP tloop ; All over again
;
; Receive a char and store it in the SRAM buffer
;
rx:
LDI mpr,' ' ; Transmits a blank as separator
ST X+,mpr ; Store it in the SRAM buffer and inc the pointer
IN mpr,UDR ; Get a char from the UART receiver port
MOV cc,mpr ; Make a copy of that char
SWAP mpr ; Swap upper and lower nibble of the char
ANDI mpr,0x0F ; Delete the upper nibble part
CPI mpr,10 ; Nibble > 9?
BRCS rx1 ; No
LDI h,7 ; Add 7 to get hex A to F
ADD mpr,h
rx1:
LDI h,'0' ; from 0 to '0'
ADD mpr,h
ST X+,mpr ; and copy to SRAM
ANDI cc,0x0F ; Same procedure with the lower nibble
CPI cc,10
BRCS rx2
LDI h,7
ADD cc,h
rx2:
LDI h,'0'
ADD cc,h
ST X+,cc
LDI cc,'h' ; Send 'h' to signal hex
ST X+,cc ; and copy to SRAM buffer
RJMP tloop ; and return to the main program loop
;
; Send characters stored in the SRAM-buffer, if there are such
waiting
;
tx:
CP XL,YL ; Compare input and output position
BREQ tx1 ; No chars available
LD mpr,Y+ ; Get a char from the SRAM and inc the output pointer
OUT UDR,mpr ; Transfer this char to the transmitter port
RJMP tloop ; and return back to the main program loop
tx1:
LDI XH,HIGH(RamStart) ; All sent, set the pointer to the
beginning of the SRAM
LDI XL,LOW(RamStart)
LDI YH,HIGH(RamStart)
LDI YL,LOW(RamStart)
RJMP tloop ; and return to the main program loop
;
; End Of Code
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/SIOHEX.html1/20/2009 7:56:56 PM
http://www.avr-asm-tutorial.net/avr_en/source/SIOHEX.asm

;
; Test of the Serial IO
;
; Receives charactern from the SIO with 9k6 8N1 and sends back
; their hex values as text
;
; Hardware: Serial connection between the board and a terminal
; Communication: Terminal program, e.g. HyperTerminal
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Constants
;
.EQU fq=4000000 ; XTal-frequency
.EQU baud=9600 ; Baudrate
.EQU bdteiler=(fq/(16*baud))-1 ; Baud-Divider
.EQU RamStart = 0x0060
;
; Register
;
.DEF mpr=R16 ; Universal register
.DEF cc=R17 ; Char copy
.DEF h=R18 ; Various values
;
; XL/XH = R26/R27 are used as Pointer to the SRAM (input buffer position)
; YL/YH = R28/R29 are used as Pointer to the SRAM (output buffer position)
;
; Program code starts here
;
.CSEG
;
; Reset-Vector
;
rjmp main ; Reset-vector
;
main:
ldi XH,HIGH(RamStart)
ldi XL,LOW(RamStart)
ldi YH,HIGH(RamStart)
ldi YL,LOW(RamStart)
ldi mpr,0x0D ; Start with a new line
st X+,mpr ; put to the SRAM buffer and inc input pointer
ldi mpr,0x0A ; additional linefeed
st X+,mpr
ldi mpr,bdteiler ; Set baudrate generator
out UBRR,mpr ; to divider port
ldi mpr,0b00011000 ; Enable TX and RX
out UCR,mpr ; to UART Control Register
;
; Main program loop asks UART for characters and transmits buffered chars in SRAM
;
tloop:
sbic USR,RXC ; Jump if receiver is empty
rjmp rx ; Receive the next char
sbic USR,UDRE ; Jump if the transmitter is not ready to receive chars
rjmp tx ; Send next char
rjmp tloop ; All over again
;
; Receive a char and store it in the SRAM buffer
;
rx:
ldi mpr,' ' ; Transmits a blank as separator
st X+,mpr ; Store it in the SRAM buffer and inc the pointer
in mpr,UDR ; Get a char from the UART receiver port
mov cc,mpr ; Make a copy of that char
swap mpr ; Swap upper and lower nibble of the char
andi mpr,0x0F ; Delete the upper nibble part
cpi mpr,10 ; Nibble > 9?
brcs rx1 ; No
ldi h,7 ; Add 7 to get hex A to F
add mpr,h
rx1:
ldi h,'0' ; from 0 to '0'
add mpr,h
st X+,mpr ; and copy to SRAM
andi cc,0x0F ; Same procedure with the lower nibble
cpi cc,10
brcs rx2
ldi h,7
add cc,h
rx2:
ldi h,'0'
add cc,h
st X+,cc
ldi cc,'h' ; Send 'h' to signal hex
st X+,cc ; and copy to SRAM buffer
rjmp tloop ; and return to the main program loop
;
; Send characters stored in the SRAM-buffer, if there are such waiting
;
tx:
cp XL,YL ; Compare input and output position
breq tx1 ; No chars available
ld mpr,Y+ ; Get a char from the SRAM and inc the output pointer
out UDR,mpr ; Transfer this char to the transmitter port
rjmp tloop ; and return back to the main program loop
tx1:
ldi XH,HIGH(RamStart) ; All sent, set the pointer to the beginning of the SRAM
ldi XL,LOW(RamStart)
ldi YH,HIGH(RamStart)
ldi YL,LOW(RamStart)
rjmp tloop ; and return to the main program loop
;
; End Of Code
;

http://www.avr-asm-tutorial.net/avr_en/source/SIOHEX.asm1/20/2009 7:56:57 PM
AVR-Tutorial, Requirements

Path: Home => AVR-Overview => Tutorial

Tutorial for learning the assembler


language of
AVR-Single-Chip-Processor
AT90Sxxxx
of ATMEL by programming practical
examples.
Basic requirements

Targets
The following lectures introduce to the assembly language of AVR-Single-chip-Processors of the
AT90Sxxxx series by ATMEL. After going through these examples you should be able to write
simple programs for these processors. The examples might be compiled with the ATMEL or any
other assembler, the resulting binary code should be transferred to the board and started there. Every
program step is commented.

Requirements
All examples are compatible with the ATMEL-assembler. If you use other assemblers you probably
have to change the code to meet their special syntax requirements.
The examples run directy on the STK-200-programming board, as supplied by ATMEL. For all
hardware-components on this board examples for their programming and use are supplied in
additional examples.
ATTENTION! All examples require the definition file "8515def.inc" in the same directory with the
source code, otherwise numerous error messages occur during assebling. The file could be found in
the home directory of the ATMEL software package or on ATMEL's homepage. Change the path in
the INCLUDE line from folder X:\avrtools\appnotes\ to your path or copy this file into your source
code folder.

Steps
If you're a bloody beginner in assebler and AVR processors: Load the examples test1 to test4 into
your editor one by one, read the comments in these files and try to figure out, if you understand the
single steps of the program, assemble the source code and run the binary on the STK-200 board.
For the more advanced searching for certain component code: Identify the proper example for the
component and play around with this code. Change it until it fits your needs.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_ALLG.html1/20/2009 7:56:58 PM
Demonstration of a LCD on STK200 AVR board

; *****************************************************
; * Demonstrates the use of the Include routines *
; * LCD_INC.ASM for use with the LCD on board of the *
; * ATMEL STK200 (C) 1999 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; *****************************************************
;

.NOLIST
.INCLUDE "8515def.inc"
.LIST

.def mpr=R16 ; My multipurpose register, required

; Reset-/Interrupt-Vectors

RJMP main

; Includes the LCD-routines, file must be in the same path

.INCLUDE "LCD_INC.ASM"

; Main program

main: LDI mpr,LOW(RAMEND) ; Set up stack


OUT SPL,mpr
LDI mpr,HIGH(RAMEND)
OUT SPH,mpr
LDI mpr,0xC0 ; Switch on external SRAM and WAIT
OUT MCUCR,mpr
RCALL lcd_cl ; Clears display
RCALL lcd_st ; Standard display mode
LDI mpr,0x05; Cursor position to line 1, col 5
RCALL lcd_sc
LDI mpr,'H' ; Output Hello World
RCALL lcd_ch
LDI mpr,'e'
RCALL lcd_ch
LDI mpr,'l'
RCALL lcd_ch
RCALL lcd_ch
LDI mpr,'o'
RCALL lcd_ch
LDI mpr,0x45 ; Cursor position to line 2, col 5
RCALL lcd_sc
LDI mpr,'W'
RCALL lcd_ch
LDI mpr,'o'
RCALL lcd_ch
LDI mpr,'r'
RCALL lcd_ch
LDI mpr,'d'
RCALL lcd_ch
LDI mpr,'!'
RCALL lcd_ch
RCALL lcd_on
loop: RJMP loop ; Uff! Next week we learn how to create and read a table

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/LCD_TEST.html1/20/2009 7:57:00 PM
Routine for the ATMEL STK200 board with an LCD connected

; ***********************************************
; * LCD-Interface routines for multi-purpose *
; * use with the ATMEL STK200 board, Version *
; * 0.1 Beta, (C) 1999 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; ***********************************************
;
; Purpose:
; Include file for the AVR assembler
; Supplies the common routines to drive an
; LCD connected to the ATMEL STK200 board
; Works best and is compatible to external
; SRAM on that board (up to 32 kB)
;
; Requires:
; mpr ... Multipurpose register, anything
; between R16 and R31, unchanged
; after all routines
; Memory-mapped operation of the LCD
; Setup of the software stack due to the use
; of relative subroutines and PUSH/POP
; LCD properly connected to the board, otherwise
; processor hangs around and waits for
; the busy flag to go down! (no timeout!)
; 39 words of program space
;
; Interfaces:
; lcd_wt Waits indefinately until the busy
; flag of the LCD is off
; lcd_fc Sends the command byte in register
; mpr to the LCD after busy is off
; lcd_cl Clears the LCD and sets cursor to
; the home position, after busy is off
; lcd_st Sets the LCD to 8-bit-transfer,
; freezes the display window and sets
; cursor to increment after busy is off
; lcd_sc Sets cursor to the display position
; in register mpr (Line 1: 00 .. 0F hex,
; Line 2: 40 .. 4F hex)
; lcd_ch Outputs the character in register
; mpr to the LCD after busy is off
; lcd_on Sets display on, cursor on and blink
;
; Adress definitions:
.equ lcd_rs = 0x8000 ; Register select = 0 adress
.equ lcd_ds = 0xC000 ; Register select = 1 adress
;
; Subroutines
;
; Wait until LCD is not busy any more
;
lcd_wt: PUSH mpr ; save register
lcd_wt1:
LDS mpr,lcd_rs ; read busy flag
ROL mpr ; Busy = Bit 7 into Carry
BRCS lcd_wt1 ; still busy, repeat
POP mpr ; restore register
RET
;
; Outputs the function command in mpr to the LCD
;
lcd_fc: RCALL lcd_wt ; Wait until not busy any more
STS lcd_rs,mpr ; Command byte to LCD
RET
;
; Clears LCD and sets cursor to home position
;
lcd_cl: PUSH mpr ; save register
LDI mpr,0x01 ; the clear command
RCALL lcd_fc ; output to LCD command
POP mpr ; restore register
RET
;
; Sets LCD to 8-bit-mode, display window freeze and
; cursor incrementation (standard mode)
;
lcd_st: PUSH mpr ; save register
LDI mpr,0b00111000 ; 8-Bit-transfer
RCALL lcd_fc ; to LCD command
LDI mpr,0b00000110 ; Increment, display freeze
RCALL lcd_fc ; to LCD
LDI mpr,0b00010000 ; Cursor move, not shift
RCALL lcd_fc ; to LCD
POP mpr ; restore register
RET
;
; Sets cursor on the LCD to a certain display position in mpr
;
lcd_sc: PUSH mpr ; save position
ORI mpr,0x80 ; set bit 7 of the position
RCALL lcd_fc ; position to LCD
POP mpr ; restore register
RET
;
; Sends a character in mpr to the display at the current
; position, position is incremented after write
;
lcd_ch: RCALL lcd_wt ; wait for not busy
STS lcd_ds,mpr ; transfer character to LCD-Display
RET
;
; Sets LCD display on, cursor on and blink on
;
lcd_on: PUSH mpr ; save register
LDI mpr,0b00001111 ; command byte
RCALL lcd_fc ; to LCD
POP mpr ; restore register
RET

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/LCD_INC.html1/20/2009 7:57:02 PM
Test of a 16-swich keypad

; Test of a 16-switch keypad


;
; Reads the keyboard on port B and displays the activated key on the LEDs
; in hex format.;
; The decimal keyboard is attached to port B:
; Bit 6: *=Bit0 7=Bit1 4=Bit2 1=Bit3
; Bit 5: 0=Bit0 8=Bit1 5=Bit2 2=Bit3
; Bit 4: #=Bit0 9=Bit1 6=Bit2 3=Bit3
;
; Tests with this program showed that parallel operation of the LEDs and
; of the keyboard on the same port (B) is practically impossible due to
; insufficient driving currents of the port pins. No correct values are read.
;
; 8515-Definitions
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Registers
.def mpko=R15 ; Former key status
.def mpr=R16 ; Multi funktion register
.def mpk=R25 ; Multi funktion register for keyboard-Interrupts
;
; RAM-Adresses
.equ taste=$0060 ; First Ramadress, keys are here
;
; Reset-/Interruptvector table
RJMP main
RETI ; Ext Int 0
RETI ; Ext Int 1
RETI ; TC1 Capture
RJMP test ; TC1 Compare A
RETI ; Compare B
RETI ; TC1 Overflow
RETI ; TC0 Overflow
RETI ; Serial Transfer Complete
RETI ; Serial Rx Complete
RETI ; Data Register Empty
RETI ; Serial Tx Complete
RETI ; Analog Comparator

; Main program
main:
LDI mpr,HIGH(RAMEND) ; Stack Pointer Init for Interrupts
OUT SPH,mpr
LDI mpr,LOW(RAMEND)
OUT SPL,mpr

; General control register


CLR mpr ; no SRAM use, no Wait, no Sleep-Mode,
OUT MCUCR,mpr ; Ext.Int not used

; Port B is output and keypad-Input


LDI mpr,0x70 ; all to Output
OUT DDRB,mpr
LDI mpr,0x00 ; all lamps on
OUT PORTB,mpr
STS Taste,mpr
;
; Timer/Counter 0 init
LDI mpr,$00 ; Prescaler = 256
OUT TCCR0,mpr

; Timer 1 init
LDI mpr,0b00000000 ; Disable Timer Output and PWM-Mode
OUT TCCR1A,mpr ; in Timer Control Register 1A
LDI mpr,0b00001011 ; No input noise canceling, clear counter after
; match, Prescaler = 64 ==> 62500 Hz = 16 µs
OUT TCCR1B,mpr ; in Timer Control Register 1B
LDI mpr,HIGH(625) ; Compare-value in Compare-Register A
OUT OCR1AH,mpr ; High Byte first
LDI mpr,LOW(625)
OUT OCR1AL,mpr ; Low Byte last
LDI mpr,0xFF ; No Interrupt on Compare B
OUT OCR1BH,mpr ; High Byte first
OUT OCR1BL,mpr ; Low Byte last

; Interrupts start here


CLR mpr ; External interrupts disable
OUT GIMSK,mpr ; to General Interrupt mask register
LDI mpr,0b01000000 ; Timer 1: Overflow Int Off, Compare A nt on,
OUT TIMSK,mpr ; Compare B Int Off, Input Int Off, Timer 0: Int Off
SEI ; Interrupt enable

; Indefinit loop, all Interrupt-controlled


loop: RJMP loop

; Interrupt Routine at TC1 Compare Match B


tc1ci: IN mpk,SREG ; save Status-Register
PUSH mpk
LDI mpk,0b11110000 ; Upper nibble output, lower input
OUT DDRB,mpk ; to Port B direction
LDI mpk,0x0F ; Upper nibble =0, lower sets Pullups on
OUT PORTB,mpk
IN mpk,PINB ; Read results from keypad
CP mpk,mpko ; Compare with older status
BREQ tc1cir ; No change, return
MOV mpko,mpk ; Copy new status over old status
STS taste,mpk ; New LED-Status
tc1cir: LDI mpk,0xFF ; Port B to output
OUT DDRB,mpr
LDS mpk,taste ; status on LEDs
OUT PORTB,mpk
POP mpk ; Return from Interrupt
OUT SREG,mpk ; restore Status-Register
RETI

tc0ci: LDI mpr,0xFF


OUT PORTB,mpr
RETI
tc2ci: LDI mpr,0xAA
OUT PORTB,mpr
RETI
test:
; LDI mpk,0x0F
; OUT DDRB,mpk
; LDI mpk,0xF0
; OUT PORTB,mpk
RETI

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTKBD.html1/20/2009 7:57:05 PM
AVR-Applications

Path: Home => AVR-Overview => Applications

AVR-Single-Chip-Processor
AT90Sxxxx
of ATMEL in practical examples.

The following examples are small applications to test and use these processors practically and to
demonstrate their usefulness. All applications were tested, but I cannot guarantee their correct
function.
HTML- ASM-
Short description Link
Format Format
SIO controlled digital clock in a 2313. Could be
synchronized with the time normal DCF77, operated GIF
Clock Clock
on 77.5 kHz in the VLF band in Germany. Wiring see PDF
the Links.
PCM-encoded remote control signals in a length from
0.8 to 2.2 ms are decoded using a AT90S2323 on a
PcmDec PcmDec PcmDec
small test board and convert it to a analogue voltage
of 0 to 5 Volts.
Pulse generator, generates exact signals of a desired
duration and frequency, times are controlled by input
PwgSio PwgSio PwgSio
from an ANSI-compatible terminal program via the
SIO of the chip, e.g. on the STK200 board.
Signal generator with frequency and pulse-width
Main program, adjustment, normal and inverted digital outputs,
LCD routines, Zipped sources frequency/time/rpm/pulse-width display on LCD, RectGen
Freq table applying an ATmega8 with ADC channels, Xtal
source clock, etc.
Description
Frequency counter with ATmega8, nine modes, 16
fcount_m8_v3 fcount_V03 Scheme
MHz xtal
Preamp
eggtimer_asm eggtimer Eggtimer with an ATtiny2313V as a gift eggtimer
steppermotor steppermotor Stepper motor controller and driver with an ATtiny13

©2002-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/APPS.html1/20/2009 7:57:07 PM
XTal Clock on a AT90S2313, DCF synchronized

Path: Home => AVR-Overview => Applications => Clock

XTal Clock on a AT90S2313, DCF synchronized


; ***************************************************************
; * DCF-synchronized Digital Clock for RS232 communication on *
; * a 2313-Experimental-Board, Version 0.2 as of 12.01.2001 *
; * Features: XTal driven digital clock for exact date and time *
; * information, adjusted and read over a SIO-I/O 9k6 8N1 *
; * connection, Self-adjusting date- and time-synchronisation *
; * to a connected receiver for the Frankfurt/Germany based *
; * official clock reference DCF77 (optional) *
; * (C)2001 by Gerhard Schmidt *
; * report bugs to info!at!avr-asm-tutorial.net *
; ***************************************************************
;
; Hardware requirements:
; - 2313 board (see extra doc)
; - RS232 compatible terminal, e.g. PC+Win+HyperTerminal to
adjust/read
; the date and time informationen
; - (RXD/TXD, RTS/CTS)-crosswired RS232 cable connection between
the
; 2313-board and the terminal
; - Optional: DCF77 clock with active low receiver signal (second
ticks)
;
; Software features:
; - Interrupt-driven and buffered SIO-I/O with RTS/CTS hardware
protocol
; - Interrupt-driven clock signals with exact timing
; - SLEEP mode for reduced power consumption of the MPU
; - Exact date calculation from 2001 up to the year 2099
; - Transmits ANSI color codes for terminal control
; - DCF synchronisation: self-adjusting to unexact signal
lengthes and
; spurious signals by software, loss-of-signal-detection, full
parity bit
; checking, convenient hardware debugging opportunities by
terminal display
; of the signal length and all detected errors during the
sampling process
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2313def.inc"
.LIST
;
; Constants
;
; Constants for Sio properties
.EQU fq=10000000; Xtal frequency on board in Hz
.EQU baud=9600; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.EQU ticks=fq/16000; ticks per second for the timing functions
; Constants for Sio communications
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cBs=0x08; Backspace character
; Bit assignment of the RTS and CTS pins on Port B
.EQU bIRts = 2
.EQU bOCts = 4
; Locations in the Internal SRAM
.EQU sDTF = 0x60 ; Date/Time information, first location in SRAM
.EQU dDDT = 0 ; relative distance, Tens of Days
.EQU dDD = 1 ; relative distance, Days
.EQU dDMT = 3 ; relative distance, Tens of Monthes
.EQU dDM = 4 ; relative distance, Month
.EQU dDY = 9 ; relative distance, Years
.EQU dTHT = 12 ; relative disance, Tens of Hours
.EQU dTH = 13 ; relative distance, Hours
.EQU dTMT = 15 ; relative distance, Tens of Minutes
.EQU dTM = 16 ; relative distance, Minutes
.EQU dTST = 18 ; relative distance, Tens of Seconds
.EQU dTS = 19 ; relative distance, Seconds
.EQU sDTL = 0x74 ; Date/Time information, last location in SRAM
.EQU sDTT = 0x6C ; Position of Time
.EQU sSec = 0x73 ; Adress of seconds
.EQU sSecT = 0x72 ; Adress of tens of seconds
.EQU sMin = 0x70 ; Adress of minutes
; Constants for Sio Rx- and Tx-Buffers
.EQU RxBuF = 0x75 ; Sio Rx-Buffer, first location in SRAM
.EQU RxBuL = 0x84 ; Sio Rx-Buffer, last location in SRAM (16
Bytes)
.EQU TxBuF = 0x85 ; Sio Tx-Buffer, first location in SRAM
.EQU TxBuL = 0xA4 ; Sio Tx-Buffer, last location in SRAM (32
Bytes)
;
; Used registers
;
; Register mainly for Program Memory Read Operations
.DEF rlpm = R0 ; Used for read operations with LPM
; SIO Tx Buffer In pointer
.DEF rsiotxin = R1
; Registers for the DCF77-Receiver option
.DEF rdcfp = R2 ; Parity bit counter for DCF signals
.DEF rdcf1 = R3 ; Last Receiver Shift Register
.DEF rdcf2 = R4 ; Receiver Shift register
.DEF rdcf3 = R5 ; Receiver Shift register
.DEF rdcf4 = R6 ; Receiver Shift register
.DEF rdcf5 = R7 ; First Receiver Shift Register
.DEF rDcfCmp = R8 ; Compare length of DCF pulse (self-adjusted)
.DEF rDcfLc = R9 ; Last count length detected
.EQU cDcfCmpDflt = 125 ; Default length for DCF signals (self-
adjusted)
.DEF rDcfCnt = R10 ; DCF length count, interrupt driven
.DEF rDcfL0 = R11 ; Distance of last short pulse from medium
count length
.DEF rDcfL1 = R12 ; Distance of last long pulse from medium count
length
; For all purposes
.DEF rmpr = R16 ; Multi-purpose register
; Low level ticker for seconds counting by interrupt (1.6 ms)
.DEF rtckh = R17 ; MSB
.DEF rtckl = R18 ; LSB
; DCF77 Tick register for signal length, driven by timer interrupt
(1.6 ms)
.DEF rDcfl = R19
; Timer 0 flag register with the following bits:
.DEF rdtf = R20 ; Date/Time Flag register
.EQU bEos = 0 ; Bit 0: End of second reached
.EQU mEos = 1
.EQU bMin = 1 ; Bit 1: Echo minutes only
.EQU mMin = 2
.EQU bDTm = 2 ; Bit 2: DT mode active
.EQU mDTm = 4
; Bits used by DCF77:
.EQU bDcfm = 3 ; Bit 3: DCF mode active
.EQU mDcfm = 8
.EQU bDcfCtm = 4 ; Bit 4: DCF echo counters
.EQU mDcfCtm = 16
.EQU bDcfSync = 5 ; Bit 5: DCF synch tickers at next second
.EQU mDcfSync = 32
.EQU bDcfRdy = 6 ; Bit 6: DCF bit ready
.EQU mDcfRdy = 64
.EQU bDcfOk = 7 ; Bit 7: DCF Signal is ok
.EQU mDcfOk = 128
; SIO flag register
; Bit 5: Unused
; Bit 6: Unused
; Bit 7: Unused
.DEF rsioflg = R21 ; SIO flag register
.EQU bEcho = 0 ; Bit 0: Echo all incoming characters
.EQU mEcho = 1
.EQU bAddLf = 1 ; Bit 1: Insert LF after CR
.EQU mAddLf = 2
.EQU bTxBAct = 2 ; Bit 2: Transmitter buffer active
.EQU mTxBAct = 4
.EQU bTxAct = 3 ; Bit 3: Character transmission active
.EQU mTxAct = 8
.EQU bRxCmp = 4 ; Bit 4: Rx-Line complete
.EQU mRxCmp = 16
; DCF error flag register
.DEF rDcfErr = R22 ; Last DCF-error
.EQU bDcfPem = 0 ; Bit 0: Parity error minute
.EQU mDcfPem = 1
.EQU bDcfPeh = 1 ; Bit 1: Parity error hour
.EQU mDcfPeh = 2
.EQU bDcfPed = 2 ; Bit 2: Parity error date
.EQU mDcfPed = 4
.EQU bDcfCts = 3 ; Bit 3: Count too short
.EQU mDcfCts = 8
.EQU bDcfCtl = 4 ; Bit 4: Count too long
.EQU mDcfCtl = 16
.EQU bDcfSok = 5 ; Bit 5: Synchronisation ( not an error!)
.EQU mDcfSOk = 32
.EQU bDcfEtr = 6 ; Bit 6: Error to be reported
.EQU mDcfEtr = 64
.EQU bDcfAny = 7 ; Bit 7: Any error
.EQU mDcfAny = 128
; DCF shift register counter
.DEF rDcfs = R23 ; Shift Register Bit Counter
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-vectors
;
RJMP Start ; Reset-vector
RJMP IInt0 ; External Interrupt Request 0
RJMP IInt1 ; External Interrupt Request 1
RJMP TCpt1 ; Timer/Counter1 Capture event
RJMP TCmp1 ; Timer/Counter1 Compare match
RJMP TOvf1 ; Timer/Counter1 Overflow
RJMP TOvf0 ; Timer/Counter0 Overflow
RJMP URxAv ; Uart Rx char available
RJMP UTxDe ; Uart Tx data register empty
RJMP UTxCp ; Uart Tx complete
RJMP AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0: Started by a negative edge on the DCF input
;
IInt0:
PUSH rmpr
IN rmpr,SREG
SBRS rdtf,bDcfSync
RJMP IInt01
CBR rdtf,mDcfSync ; Synchronize DCF and internal tickers
CLR rtckl
CLR rtckh
IInt01:
CLR rDcfl
OUT SREG,rmpr
POP rmpr
RETI
;
; External Interrupt 1 : Started by a positive edge on the DCF input
;
IInt1:
PUSH rmpr
IN rmpr,SREG
CPI rDcfl,10 ; Exclude short signals
BRCS IInt1r
MOV rDcfCnt,rDcfl ; Store count length
INC rDcfs
SBR rdtf,mDcfRdy ; Flag received bit ready
IInt1r:
OUT SREG,rmpr
POP rmpr
RETI
;
; Timer/Counter 1, Capture event interrupt, not used
;
TCpt1:
RETI
;
; Timer/Counter 1, Compare match interrupt, not used
;
TCmp1:
RETI
;
; Timer/Counter 1, Overflow interrupt, not used
;
TOvf1:
RETI
;
; Timer/Counter 0, Overflow interrupt, used to count times
;
TOvf0:
PUSH rmpr ; Save Register rmpr
LDI rmpr,6 ; Set Counter to 6 to int after 250 ticks
OUT TCNT0,rmpr
IN rmpr,SREG ; Save status register
INC rtckl
BRNE TOvf0a
INC rtckh
TOvf0a:
CPI rtckl,LOW(ticks) ; End of second reached?
BRNE TOvf0b
CPI rtckh,HIGH(ticks)
BRNE TOvf0b
SBR rdtf,mEos ; Set End of second flag
CLR rtckl
CLR rtckh
TOvf0b:
INC rDcfl ; DCF77 counter tick
BRNE TOvf0c
DEC rDcfl
TOvf0c:
OUT SREG,rmpr ; Restore anything
POP rmpr
RETI
;
; Uart Rx Complete Interrupt
;
URxAv:
PUSH rmpr ; Save mpr register
IN rmpr,SREG ; Save SREG
PUSH rmpr
SBIC USR,FE ; Framing error?
RJMP URxAv2
IN rmpr,UDR ; Read Char
SBRC rsioflg,bEcho
RCALL siotxch ; Echo character
CPI rmpr,cBs ; Backspace?
BRNE URxAv0
CPI XL,RxBuF+1 ; Backspace
BRCS URxAv3
DEC XL
RJMP URxAv3
URxAv0:
ST X+,rmpr ; Store in RX buffer
CPI XL,RxBuL+1 ; End of buffer reached?
BRCS URxAv1
LDI XL,RxBuF
URxAv1:
CPI rmpr,cCr ; End of input line?
BRNE URxAv3
SBR rSioFlg,mRxCmp ; Set Line complete flag
RJMP URxAv3
URxAv2:
IN rmpr,UDR ; Clear Framing error bit
URxAv3:
POP rmpr ; Restore SREG
OUT SREG,rmpr
POP rmpr ; Restore rmpr
RETI
;
; Uart Data register empty interrupt
;
UTxDe:
PUSH rmpr ; Save register
IN rmpr,SREG ; Save status register
PUSH rmpr
CP YL,rsiotxin ; Compare Buffer In and Out
BRNE UTxDeCh
UTxDeOff:
CBR rSioFlg,mTxBAct ; No more chars to send
RJMP UTxDeRet
UTxDeCh:
SBIC PortB,bIRts ; RTS input ready?
RJMP UTxDeOff
LD rmpr,Y+ ; Read char
OUT UDR,rmpr
CPI YL,TxBuL+1 ; Check end of buffer
BRCS UTxDeRet
LDI YL,TxBuF ; Point to buffer start
UTxDeRet:
POP rmpr ; Restore status register
OUT SREG,rmpr
POP rmpr ; Restore register
RETI
;
; Uart Tx complete interrupt
;
UTxCp:
PUSH rmpr
IN rmpr,SREG
CBR rsioflg,mTxAct ; Clear the flag (not used here)
OUT SREG,rmpr
POP rmpr
RETI
;
; Analog comparator interrupt
;
AnaCp:
RETI
;
; ******* End of interrupt service routines ***********
;
; Sio service subroutines to be called from various sources
;
;
; Char in rmpr to Tx-Buffer
;
siotxch:
SBIC PortB,bIRts ; Send only, if RTS is active
RET
PUSH ZH
PUSH ZL
CLR ZH ; Point to TX buffer input position
MOV ZL,rSioTxIn
ST Z+,rmpr
CPI ZL,TxBuL+1 ; End of buffer reached?
BRCS siotxchx
LDI ZL,TxBuF
siotxchx: ; Wait here to avoid buffer overrun
CP ZL,YL
BREQ siotxchx
CLI ; Enter critical situation, disable interrupts
SBRC rsioflg,bTxBAct
RJMP sioTxChy
SBR rsioflg,mTxBAct
OUT UDR,rmpr
RJMP sioTxChn
sioTxChy:
MOV rsioTxIn,ZL
sioTxChn:
SEI ; End of critical situation
POP ZL
POP ZH
CPI rmpr,cCr ; Add linefeeds after carriage return?
BRNE sioTxChz
SBRS rsioflg,bAddLf
RJMP sioTxChz
LDI rmpr,cLf
RCALL sioTxCh
LDI rmpr,cCr
sioTxChz:
RET
;
; Transmits a null-terminated text from memory that Z points to
;
TxTxt:
PUSH rlpm
PUSH rmpr
TxTxt1:
LPM ; Read a char from the program memory at Z
MOV rmpr,rlpm
CPI rmpr,cnul ; End of text?
BREQ TxTxtz
RCALL siotxch
ADIW ZL,1
RJMP TxTxt1
TxTxtz:
POP rmpr
POP rlpm
RET
;
; Send date/time to SIO
;
DispDT:
RCALL DcfErr
CLR ZH ; Send time info in SRAM to SIO
LDI ZL,sDTF
DispDT1:
LD rmpr,Z+ ; Read from SRAM
RCALL siotxch ; Transmit
CPI rmpr,cCr ; Last char?
BRNE DispDT1
RET
;
; Send a byte as decimal number to the SIO
;
DispByte:
RCALL siotxch ; preface
LDI rmpr,' '
RCALL siotxch
LDI rmpr,'='
RCALL siotxch
LDI rmpr,' '
RCALL siotxch
LDI ZH,100 ; send 100's
SUB ZL,ZH
BRCS DispByte1
LDI rmpr,'1'
SUB ZL,ZH
BRCS DispByte1
SUB ZL,ZH
INC rmpr
DispByte1:
RCALL siotxch
ADD ZL,ZH
LDI ZH,10 ; send 10's
SUB ZL,ZH
BRCS DispByte3
LDI rmpr,'0'
DispByte2:
INC rmpr
SUB ZL,ZH
BRCC DispByte2
RJMP DispByte4
DispByte3:
CPI rmpr,' '
BREQ DispByte4
LDI rmpr,'0'
DispByte4:
ADD ZL,ZH
RCALL siotxch
LDI rmpr,'0' ; send 1's
ADD rmpr,ZL
RCALL siotxch
LDI rmpr,' '
RCALL siotxch
RJMP siotxch
; ************** End of SIO subrourines *******************
;
; ***************** Various subroutines *******************
;
; DT mode active, display date/time
;
DTModeX:
SBRS rdtf,bMin ; Minutes only?
RJMP DTModeX1
LDS rmpr,sSec ; End of minute?
CPI rmpr,'0'
BRNE DTModeX2
LDS rmpr,sSecT
CPI rmpr,'0'
BRNE DTModeX2
DTModeX1:
RCALL DispDT ; Display date and time
DTModeX2:
RET ; Return to loop
;
; DCF mode active, display DCF characteristics
;
DCFModeX:
RCALL DcfErr ; Report any DCF77 errors first
SBRC rdtf,bDcfCtm
RJMP DCFModeX2
OR rDcfs,rDcfs ; Report DCF signals bitwise
LDI rmpr,cCr
BREQ DCFModeX1
DEC rDcfLc
LDI rmpr,'1'
CP rDcfLc,rDcfCmp
BRCC DCFModeX1
DEC rmpr
DCFModeX1:
RJMP siotxch
DCFModeX2:
LDI rmpr,'b' ; Report signal number
MOV ZL,rDcfs
RCALL DispByte
LDI rmpr,'c' ; Report detected signal length in ticks
MOV ZL,rDcfLc
RCALL DispByte
LDI rmpr,'m' ; Report current discriminating value
MOV ZL,rDcfCmp
RCALL DispByte
LDI rmpr,cCr
RJMP siotxch
;
; Reports any DCF errors
;
DcfErr:
SBRS rDcfErr,bDcfEtr ; Any unreported errors?
RET
CBR rDcfErr,mDcfEtr
LDI ZH,HIGH(2*TxtDcfErr) ; Error text intro
LDI ZL,LOW(2*TxtDcfErr)
RCALL TxTxt
MOV rmpr,rDcfErr
ANDI rmpr,0x3F
DcfErr1:
ADIW ZL,1
CLC ; Identify next error bit
ROR rmpr
BRCC DcfErr3
RCALL TxTxt
DcfErr2:
OR rmpr,rmpr ; No more bits set?
BRNE DcfErr1
ANDI rDcfErr,0x80
LDI rmpr,cCr
RJMP siotxch
DcfErr3:
ADIW ZL,1 ; Point to next text sequence
LPM
OR rlpm,rlpm
BRNE DcfErr3
RJMP DcfErr2
;
; DCF synchronisation
;
Dcf:
CLR rDcfs ; End of minute, clear bit counter
SBR rDcfErr,(mDcfSOk | mDcfEtr) ; Set synch to be reported
LDI rmpr,'0'
CLR ZH
LDI ZL,sSec ; Second
ST Z,rmpr
ST -Z,rmpr
DEC ZL
DEC ZL
MOV rmpr,rDcf1 ; Minute
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf2 ; Tens of minutes
ROR rmpr
MOV rmpr,rDcf1
ROR rmpr
ROR rmpr
SWAP rmpr
ANDI rmpr,0x07
ORI rmpr,0x30
ST -Z,rmpr
DEC ZL ; Hour
MOV rmpr,rDcf2
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST -Z,rmpr
MOV rmpr,rDcf2 ; Tens of hours
ROL rmpr
ROL rmpr
ROL rmpr
ANDI rmpr,0x03
ORI rmpr,0x30
ST -Z,rmpr
LDI ZL,sDTF+dDD ; Day
MOV rmpr,rDcf3
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf3 ; Tens of Days
ROR rmpr
SWAP rmpr
ANDI rmpr,0x03
ORI rmpr,0x30
ST -Z,rmpr
ADIW ZL,4 ; Month
MOV rmpr,rDcf4
ROR rmpr
ROR rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf4 ; Tens of monthes
SWAP rmpr
ROR rmpr
ROR rmpr
ANDI rmpr,0x01
ORI rmpr,0x30
ST -Z,rmpr
ADIW ZL,6 ; Years
MOV rmpr,rDcf4
ROL rmpr
MOV rmpr,rDcf5
ROL rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST Z,rmpr
MOV rmpr,rDcf5 ; Tens of years
ROL rmpr
SWAP rmpr
ANDI rmpr,0x0F
ORI rmpr,0x30
ST -Z,rmpr
RET
;
; Next second
;
ChkDcf:
; Check DCF77 info complete
CBR rdtf,mEos ; Clear seconds flag bit
SBRC rdtf,bDcfOk ; Last DCF tick was ok?
RJMP NewDcfSec
SBR rdtf,mDcfSync ; Minute is over
MOV rmpr,rDcfs ; Have all 59 DCF ticks been received?
CPI rmpr,59
BRCS CntTooShort ; Less than 59 ticks
BRNE CountTooLong ; More than 59 ticks
SBRS rDcfErr,bDcfAny ; Any errors in parity?
RJMP Dcf
RJMP CntReset ; No DCF synch, clear all
CountTooLong:
SBRS rdtf,bDcfm ; DCF echo mode on?
RJMP CntReset
SBR rDcfErr,(mDcfCtl | mDcfEtr | mDcfAny) ; Set DCF error
type
RJMP CntReset
CntTooShort:
SBR rDcfErr,mDcfCts ; Set DCF error type
OR rDcfs,rDcfs ; DCF shift register totally empty?
BREQ CntReset
SBR rDcfErr,(mDcfEtr | mDcfAny) ; Set error to report
CntReset:
CLR rDcfs ; Clear the DCF shift counter
CBR rDcfErr,mDcfAny ; Clear the global DCF error bit
NewDcfSec:
CBR rdtf,mDcfOk ; Clear the DCF tick ok bit
IncSec:
CLR ZH ; Point to Date/Time info in SRAM
LDI ZL,sDTF+dTS ; Second
RCALL IncNmbr ; Next second and handle overflow
CPI rmpr,60 ; end of minute?
BRCC IncMin
IncRet:
RET
IncMin:
LDI rmpr,'0' ; Clear seconds
ST Z,rmpr
ST -Z,rmpr
LDI ZL,sDTF+dTM ; Next minute
RCALL IncNmbr
CPI rmpr,60 ; End of the hour?
BRCS IncRet
IncHour:
LDI rmpr,'0' ; Clear minutes
ST Z,rmpr
ST -Z,rmpr
LDI ZL,sDTF+dTH ; Next hour
RCALL IncNmbr
CPI rmpr,24 ; End of the day?
BRCS IncRet
LDI rmpr,'0' ; Clear hours
ST Z,rmpr
ST -Z,rmpr
IncDay:
LDI ZL,sDTF+dDD ; Next day
RCALL IncNmbr
CPI rmpr,32 ; End of month?
BRCC IncMonth
CPI rmpr,31 ; End of month for short monthes
BRNE ChkFeb
LDI ZL,sDTF+dDM ; Get days
RCALL GetByte
SUBI rmpr,4 ; Before April?
BRCS IncRet
CPI rmpr,3 ; April or June?
BRCS IncDay1
INC rmpr ; Later than June
IncDay1:
SBRC rmpr,0 ; Even month?
RET
RJMP IncMonth ; End of a short month
ChkFeb:
LDI ZL,sDTF+dDM ; Get current month
RCALL GetByte
CPI rmpr,2 ; February?
BRNE IncRet
LDI ZL,sDTF+dDY ; Get year
RCALL GetByte
ANDI rmpr,0x03 ; February with 29 days?
BRNE ChkFeb1
LDI ZL,sDTF+dDD ; Get current day
RCALL GetByte
CPI rmpr,30 ; Long February ends with 29
RJMP ChkFeb2
ChkFeb1:
LDI ZL,sDTF+dDD ; Short February, get actual day
RCALL GetByte
CPI rmpr,29 ; End of month?
ChkFeb2:
BRCS IncRet
IncMonth:
LDI ZL,sDTF+dDD ; Next month, clear days
LDI rmpr,'1'
ST Z,rmpr
LDI rmpr,'0'
ST -Z,rmpr
LDI ZL,sDTF+dDM ; Next month
RCALL IncNmbr
CPI rmpr,13 ; End of the year?
BRCS IncRet
IncYear:
LDI rmpr,'1' ; next year, clear month
ST Z,rmpr
LDI rmpr,'0'
ST -Z,rmpr
LDI ZL,sDTF+dDY ; Inc years by running into the following
;
; Inc Number at Z and Z-1 and return with the number in one byte
;
IncNmbr:
LD rmpr,Z ; Inc's a number in SRAM and its tens, if necessary
INC rmpr
CPI rmpr,'9'+1
BRCS IncNmbr1
LD rmpr,-Z
INC rmpr
ST Z+,rmpr
LDI rmpr,'0'
IncNmbr1:
ST Z,rmpr
;
; Get byte from Z and Z-1
;
GetByte:
LD rmpr,-Z ; Two digit number to binary, load first digit
SUBI rmpr,'0'
MOV rlpm,rmpr ; Multiply by 10
ADD rmpr,rmpr
ADD rmpr,rmpr
ADD rmpr,rlpm
ADD rmpr,rmpr
MOV rlpm,rmpr ; Store result in rlpm
INC ZL ; Add second digit
LD rmpr,Z
SUBI rmpr,'0'
ADD rmpr,rlpm
RET
; **************** End of the subroutine section ***************
;
; ******************** Main program loop ***********************
;
; Main program routine starts here
;
Start:
CLI ; Disable interrupts
LDI rmpr,RAMEND ; Set stack pointer
OUT SPL,rmpr
RCALL InitDT ; Init Date/Time-Info in SRAM
RCALL InitIo ; Init the I/O properties
RCALL InitSio ; Init the SIO properties
RCALL InitDcf
RCALL InitTimer0 ; Init the timer 0
RCALL InitAna ; Init the Analog comparator
; General Interrupt Mask Register
; External Interrupt Request 1 Enable
; External Interrupt Request 0 Enable
LDI rmpr,0b11000000
OUT GIMSK,rmpr
; Timer/Counter Interrupt register
; Disable all TC1 Ints
; Enable TC0 Ints
LDI rmpr,0b00000010
OUT TIMSK,rmpr
; Enable interrupts (Master Int Enable)
SEI ; Enable all interrupts
; Master Control register settings
; Sleep Enable, Sleep Mode = Idle
; Ext Int 1 on rising edges
; Ext Int 0 on falling edges
LDI rmpr,0b00101110
OUT MCUCR,rmpr
Loop:
SLEEP ; Sleep until interrupt occurs
NOP ; needed to wakeup
SBRS rdtf,bDcfRdy ; Check if DCF signal has ended
RJMP ChkEos ; no, inc the seconds
CBR rdtf,mDcfRdy ; DCF: clear active signal ended
MOV rDcfLc,rDcfCnt
CP rDcfCmp,rDcfLc ; Count parity information, is it a 1 or a
0?
BRCC DcfPar
INC rDcfp ; Count 1's
DcfPar:
CPI rDcfs,21 ; Start of minute information?
BRCS DcfCrct
BRNE DcfPar1
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar1:
CPI rDcfs,29 ; Minute parity to check?
BRNE DcfPar2
SBRC rDcfp,0 ; Parity even?
SBR rDcfErr,(mDcfPem | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar2:
CPI rDcfs,36 ; Hour parity to check?
BRNE DcfPar3
SBRC rDcfp,0 ; Even?
SBR rDcfErr,(mDcfPeh | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear parity counter
RJMP DcfCrct
DcfPar3:
CPI rDcfs,59 ; Date parity to check?
BRNE DcfCrct
SBRC rDcfp,0 ; Even?
SBR rDcfErr,(mDcfPed | mDcfEtr | mDcfAny) ; Parity error
CLR rDcfp ; Clear Parity counter
DcfCrct:
CP rDcfCmp,rDcfLc ; Compare DCF signal length with medium
value
ROR rDcf5 ; Shift the result into the DCF 40-bit storage
ROR rDcf4
ROR rDcf3
ROR rDcf2
ROR rDcf1
SBR rdtf,mDcfOk ; Set the DCF signal ok bit
SUB rDcfCnt,rDcfCmp ; Calc distance of signal length from
medium value
BRCS DcfCrct0 ; Underflow = short pulse?
MOV rDcfL1,rDcfCnt ; Store this difference in the 1-length-
byte
MOV rmpr,rDcfL0 ; Has ever a 0-signal been received?
CPI rmpr,0
BRNE DcfCrct2

http://www.avr-asm-tutorial.net/avr_en/CLOCK.html (1 of 2)1/20/2009 7:57:12 PM


XTal Clock on a AT90S2313, DCF synchronized

DcfCrctUp:
INC rDcfCmp ; Only 1-signals received so far, adjust higher
medium
RJMP Loop
DcfCrct0:
COM rDcfCnt ; Underflow = Signal 0, negative to positive
distance
MOV rDcfL0,rDcfCnt ; Store the difference in the 0-length-
byte
OR rDcfl1,rDcfL1 ; Has ever been received a 1-signal?
BRNE DcfCrCt2
DcfCrctDwn:
DEC rDcfCmp ; All 0's, reduce medium value
RJMP Loop
DcfCrct2:
CP rDcfL1,rDcfL0 ; Compare the differences of the last 0
and 1 received
BREQ Loop
BRCS DcfCrctDwn ; Adjust the medium value according to the
difference
RJMP DcfCrctUp
ChkEos:
SBRS rdtf,bEos ; End of a timer second?
RJMP Loop2
RCALL ChkDcf ; Check if DCF is to sychronize
SBRS rDTf,bDTm ; DT mode active?
RJMP Loop1
RCALL DTModeX ; Output the results
ModeOff:
CPI XL,RxBuF ; In the time- and dcf-echo-mode only blanks
are to be
BREQ Loop ; reacted upon. Has a char been sent over the SIO?
CLR XH ; Reset RX-buffer to the start
LDI XL,RxBuF
LD rmpr,X ; Read character
CPI rmpr,' ' ; Check for BLANK
BRNE StartLoop
BLD rsioflg,bEcho ; Restore the echo bit
CBR rDTf,(mDTm | mDcfm) ; Clear the mode bits
RJMP CursorOn ; send cursor on the SIO
Loop1:
SBRS rdtf,bDcfm ; DCF mode active?
RJMP Loop2
RCALL DCFModeX ; DCF mode execution
RJMP ModeOff
Loop2:
SBRS rSioFlg,bRxCmp ; Line of chars from the SIO complete?
RJMP Loop
CBR rSioFlg,mRxCmp ; Clear line available bit
SBI PortB,bOCts ; Set hardware CTS off
CPI XL,RxBuF+1 ; Has only a carriage return been sent?
BRNE Cmnd
LDI ZH,HIGH(2*TxtIntro) ; Empty line, transmit help text
LDI ZL,LOW(2*TxtIntro)
RCALL TxTxt
CursorOn:
LDI ZH,HIGH(2*TxtCursor) ; Display cursor line again
LDI ZL,LOW(2*TxtCursor)
RCALL TxTxt
CLR XH ; Set SIO-RX buffer to start
LDI XL,RxBuF
CBI PortB,bOCts ; Set hardware clear to send active
StartLoop:
RJMP Loop
Cmnd:
LDI ZH,HIGH(2*CmdTab) ; Line received, search for command in
table
LDI ZL,LOW(2*CmdTab)
Cmnd1:
CLR XH ; Receive buffer to start
LDI XL,RxBuF
Cmnd2:
LPM ; Read a char from the command table
ADIW ZL,1
LDI rmpr,cCr ; end of the command?
CP rmpr,rlpm
BRNE Cmnd4
LPM ; next byte in command table a Carriage return char?
CP rmpr,rlpm
BRNE Cmnd3
ADIW ZL,1 ; Jump over that
Cmnd3:
LPM ; Load the command adress from the tabel and push it to
the stack
ADIW ZL,1
PUSH rlpm
LPM
ADIW ZL,1
PUSH rlpm
LDI ZH,HIGH(2*TxtYellow) ; Set terminal to different color
LDI ZL,LOW(2*TxtYellow)
RJMP TxTxt ; after transmit the return jumps to the command
adress!
Cmnd4:
LD rmpr,X+ ; compare the next char in the RX buffer
CP rmpr,rlpm
BREQ Cmnd2 ; equal, compare next
Cmnd5:
LDI rmpr,cCr ; not equal, search for next command in table
CP rmpr,rlpm ; search end of the current command name
BREQ Cmnd6
LPM ; read until a carriage return in the command table is
found
ADIW ZL,1
RJMP Cmnd5
Cmnd6:
LPM ; read over additional carriage returns
CP rmpr,rlpm
BRNE Cmnd7
ADIW ZL,1
RJMP Cmnd6
Cmnd7:
ADIW ZL,2 ; ignore the following word (command adress)
LPM
LDI rmpr,cnul ; check if the end of tabel is reached
CP rmpr,rlpm
BRNE Cmnd1
LDI ZH,HIGH(2*TxtError) ; end of table, command is unknown
LDI ZL,LOW(2*TxtError)
RCALL TxTxt
RJMP CursorOn ; receive next command line
; ************************* End of program loop *****************
;
; ********************** Initialisation routines ****************
;
; Init the Date/Time-Info in the SRAM
;
InitDT:
LDI ZH,HIGH(2*DfltDT) ; Point Z to default value in program
memory
LDI ZL,LOW(2*DfltDT)
CLR XH ; Point X to date/time info in SRAM
LDI XL,sDTF
CLR rmpr ; Test for NUL = end of default?
InitDT1:
LPM ; Read from program memory
ADIW ZL,1 ; Inc Z pointer
CP rmpr,rlpm ; Test for end
BRNE InitDT2
RET
InitDT2:
ST X+,rlpm ; Copy to SRAM location and inc X pointer
RJMP InitDT1 ; Next location
;
; Initialize the IO-properties
;
InitIo:
; Pins on Port D used:
; Bit 0: Input RxD Sio
; 1: Output TxD Sio
; 2: Input External interrupt 0, DCF signal
; 3: Input External Interrupt 1, DCF signal
; 4: Output TO, not used
; 5: Output T1, not used
; 6: ICP Input Capture Pin, not used
LDI rmpr,0b00110010 ; Port D Control
OUT DDRD,rmpr ; Data direction register
LDI rmpr,0b00001100 ; Pullup resistors on DCF input on to
avoid glitches
OUT PortD,rmpr ; on open inputs
; Pins on Port B:
; Bit 0: Input AIN2, not used
; 1: Input AIN1, not used
; 2: Input SIO incoming RTS signal
; 3: Output OC1, not used
; 4: Output SIO outgoing CTS signal
; 5: Input MOSI, programming interface
; 6: Input MISO, programming interface
; 7: Input SCK, programming interface
LDI rmpr,0b00011000 ; Port B Control
OUT DDRB,rmpr ; Data Direction Register
LDI rmpr,0b00000000 ; No pullup resistors
OUT PortB,rmpr
RET
;
; Initialize the SIO properties
;
InitSio:
LDI rsioflg,0b00000011 ; Echo on, insert LF after CR on
CLR XH ; Set Rx Buffer
LDI XL,RxBuF
LDI rmpr,TxBuF ; Set Tx Buffer In
MOV rsiotxin,rmpr
CLR YH ; Set Tx Buffer Out
LDI YL,TxBuF
LDI rmpr,bddiv ; Init baud generator
OUT UBRR,rmpr ; set divider in UART baud rate register
LDI rmpr,0b00011000 ; Enable TX and RX, disable Ints
LDI ZL,0 ; Wait for 65 ms
LDI ZH,0
InitSio1:
SBIW ZL,1
BRNE InitSio1
LDI rmpr,0b11111000 ; Enable TX und RX 8 Bit and Ints
OUT UCR,rmpr ; in UART Control Register
CBI PortB,bOCts ; Set Clear to sent active
RET
;
; Init the Timer 0
;
InitTimer0:
CLR rmpr ; Stop the Timer
OUT TCCR0,rmpr
LDI rmpr,6 ; Start with 6 to get 250 steps @ 10 MHz and
div=64
OUT TCNT0,rmpr ; to Timer register
CLR rtckl ; Clear the low-level-ticker
CLR rtckh
CLR rdtf ; Clear the flags
LDI rmpr,3 ; Divide Clock by 64
OUT TCCR0,rmpr ; to Timer 0 Control register
RET
;
; Init the Analog comparator
;
InitAna:
; Analog comparator is disabled and switched off
LDI rmpr,0b00000000
OUT ACSR,rmpr
RET
;
; Init DCF
;
InitDcf:
LDI rmpr,cDcfCmpDflt ; Set medium value to default value
MOV rDcfCmp,rmpr
CLR rDcfL0 ; Clear the distances
CLR rDcfL1
CLR rDcfErr ; Clear the error flags
RET
; *************** End of init routines *********************
;
; ********************* Commands ***************************
;
; Command Table, holds the command text and the command adress
;
CmdTab:
.DB '?',cCr ; Display list of commands
.DW Help
.DB 'd','?',cCr,cCr
.DW DateOut
.DB 'd','s',cCr,cCr ; Mode echo seconds
.DW DS
.DB 'd','m',cCr,cCr ; Mode echo minutes
.DW DM
.DB 'd','a','t','e','=',cCr ; Set Date
.DW Date
.DB 't','i','m','e','=',cCr ; Set Time
.DW Time
.DB 'd','c','f','b',cCr,cCr ; Enter DCF bit pattern mode
.DW DCFMode
.DB 'd','c','f','c',cCr,cCr ; Enter DCF counter mode
.DW DCFCntMode
.DB cnul,cnul,cnul,cnul
;
; Display list of commands
Help:
LDI ZH,HIGH(2*TxtHelp)
LDI ZL,LOW(2*TxtHelp)
RCALL TxTxt
RJMP CursorOn
; Display date and time
DateOut:
RCALL DispDT
RJMP CursorOn
; Set mode to echo date and time every second
DS:
CBR rdtf,mMin
RCALL DTMode
RJMP CursorOn
; Set mode to echo date and time every minute only
DM:
SBR rdtf,mMin
; Enter Date/Time-Echo-Mode
DTMode:
SBR rdtf,mDTm ; Set the mode bit
LDI ZH,HIGH(2*TxtDtm) ; Display the info text
LDI ZL,LOW(2*TxtDtm)
SetMode:
RCALL TxTxt
BST rsioflg,bEcho ; Store the echo bit and switch it off
CBR rsioflg,mEcho
CBI PortB,bOCts ; Clear to send active to receive characters
CLR XH ; Set RX-buffer to start
LDI XL,RxBuF
RJMP Loop
;
; Enter DCFMode
;
DCFMode:
CBR rdtf,mDcfCtm ; clear the mode bit
DCFMode1:
SBR rdtf,mDcfm ; set echo mode
LDI ZH,HIGH(2*TxtDcf) ; Display the info text
LDI ZL,LOW(2*TxtDcf)
RJMP SetMode
;
; Enter DCF counter echo mode
;
DCFCntMode:
SBR rdtf,mDcfCtm ; set the DCF echo mode bit
RJMP DCFMode1
;
; Set date
;
Date:
CLR ZH ; Point Z to Date in SRAM
LDI ZL,sDTF
Date1:
LD rmpr,X+ ; Take over char from Rx-buffer
CPI rmpr,cCr
BREQ Date2
ST Z+,rmpr
LD rmpr,Z ; End reached?
CPI rmpr,','
BREQ Date2
CPI rmpr,cCr
BRNE Date1
Date2:
RCALL DispDT ; send date and time to SIO
RJMP CursorOn ; Cursor on and back to loop
;
; Set time
;
Time:
CLR ZH ; Point Z to Time in SRAM
LDI ZL,sDTT
RJMP Date1
;
; Texts to be displayed
;
TxtIntro:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Set screen
colours
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB "Hello world!"
.DB ccr,'T'
.DB "his is the experimental 2313 board (C)DG4FAC at work. ? for
help. "
.DB cnul,cnul
TxtCursor:
.DB ccr,cesc,'[','3','2','m','*','>',cesc,'[','3','6','m',cnul
TxtYellow:
.DB cesc,'[','3','3','m',cnul
TxtError:
.DB ccr,cesc,'[','3','1','m'
.DB "Error! Unknown command! "
.DB cCr,cnul
TxtHelp:
.DB "List of commands"
.DB ':',cCr
.DB " d?: Display date/time."
.DB cCr,' '
.DB " date=dd.yy.yyyy: Set date"
.DB '.',cCr
.DB " time=hh:mm:ss: Set time."
.DB cCr,' '
.DB " ds: Display seconds"
.DB '.',cCr
.DB " dm: Display minutes."
.DB cCr,' '
.DB " dcfb: DCF77 bit pattern echo."
.DB cCr,' '
.DB " dcfc: DCF77 counter echo."
.DB cCr,' '
.DB " ?: Display this list."
.DB cCr,cNul
TxtDtm:
.DB "Date/Time echo. SPACE to leave"
.DB '.',cesc,'[','3','5','m',cCr,cnul
TxtDcf:
.DB "DCF echo mode. SPACE to leave."
.DB cesc,'[','3','4','m',cCr,cnul,cnul
TxtDcfErr:
.DB ' ',' ','D','C','F',':',' ',cNul
.DB "Minutes wrong!"
.DB ' ',cNul
.DB "Hours wrong!"
.DB ' ',cNul
.DB "Date wrong"
.DB '!',cNul
.DB "Count too short!"
.DB ' ',cNul
.DB "Count too long"
.DB '!',cNul
.DB "Synchronisation."
.DB cNul,cNul
;
; Default date and time
;
DfltDT:
.DB "11.01.2001, 23:12:58"
.DB cCr,cNul
;
; End of code segment
;
; 1015 words, only a few left in the 2313. Enough for a copyright.
;
Copyright:
.DB " 2C00 1GDF4CA"

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/CLOCK.html (2 of 2)1/20/2009 7:57:12 PM


Decoder for remote control signals

Path: Home => AVR-Overview => Applications => PCM-Decoder => Source code

;
*******************************************************************
; * PCM2PWG-Decoder for AT90S2323, Version 0.4 as of 20.12.2000
*
; * Translates pulse coded input to Pulse Width Generator Output
*
; * (C)2000 by info!at!avr-asm-tutorial.net
*
;
*******************************************************************
;
; Currently adjusted for 800 to 2200 µs signals and 4 MHz.
; Adjust constants below to fit to other timings!
;
; VCC LED PWG PCM PCM-Inp: 25ms = 40 Hz cycle time
; Out Out Inp active high pulse encoded
signal
; +-8----7----6----5--+
; | | PWG-Out: 1.4 ms = 714 Hz cycle time
; O AT 90 S 2323 | active high for 0..1.4 ms
; | |
; +-1----2----3----4--+ LED-Out: Active low if error occurs
; RST XT1 XT2 GND
;
; ********* Input Signal PCM encoded **************************
;
; Phase I II III IV V VI VII
; PCM 1---- -------------------- ------
; Inp \\\\\ / \\\\\\\\\\\\ /
; 0------------ ------------------------
;
; ********* Output Signal Pulse Width Generator ***************
;
; PWG 1 ------------- ------
; Out / \ /
; 0---- -------------
; Time µs |<--0..cCycl->|<-cCycl..0-->| 800 - 2200 µs:
; |<----------cCycl---------->| cCycl = 1400 µs
;
; *************************************************************
;
.NOLIST
.INCLUDE "2323def.inc"
.LIST
;
; Used registers
;
.DEF rmpr = R16 ; Multi Purpose register
.DEF rdel = R17 ; Register for delay loops
.DEF rpwc = R18 ; Counter for pulse width generator
.DEF rpws = R19 ; Current setting of pulse width generator
.DEF rpwn = R20 ; Next setting of the pulse width generator
.DEF rtry = R21 ; Number of retries
.DEF rctr = R22 ; Counter for active cycles
.DEF rerr = R23 ; Number of failures
; ZL = R30 and ZH = R31 used for counting long times
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Output pins
.EQU bIn = 0 ; Input pin is 0, active high
.EQU bOut = 1 ; Output pin for PWG, pulse width generator
.EQU bFail = 2 ; Output pin for failure LED, active low
;
; Constants (1 cycle = 6 µs = 24 clock cycles @ 4 MHz)
;
; Adjust the xtal frequency for other clocks
;
.EQU cXtal = 4 ; Crystal frequency in MHz
;
; Adjust this cycle length for other total lengthes of the input
signal
;
.EQU cPulseDuration = 25000 ; Total pulse length in µs
;
; Adjust the timing for other active high encoder pulses
;
.EQU cMinPulse = 800 ; Minimum pulse length in µs
.EQU cMaxPulse = 2200 ; Maximum pulse length in µs
;
; Adjust this fallback value in % of total duration if errors or
; signal-losses occur, 0%: Output is low, 100%: output is high,
; 50%: Output is 50% pulse width
;
.EQU cFallBackValue = 50 ; 50% pulse width
;
; The following are automatically calculated from the above,
; don't adjust these without knowing what you do!
;
.EQU cUnitLength = 24 ; Clock cycles per unit loop
.EQU cCycleLength = cUnitLength/cXtal ; Total cycle length in µs
.EQU cCycl = cPulseDuration/cCycleLength ; Cycles in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Active cycles
.EQU cTolerance = cStep/10; Tolerated short/long signal length
.EQU cMinSteps = cMinPulse/cCycleLength ; Start counting active
pulse
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Stop counting active pulse
.EQU cMin1 = cMinSteps-cTolerance-1 ; Unit loops that must be
active high
.EQU cTlp = cTolerance-1 ; Early low units that are tolerated as
Zero
.EQU cTla = cTolerance ; Late units tolerated as One
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Units that must be inactive
.EQU cFbck = 1 ; Number of false signals to tolerate before default
is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default fallback value for
PWG
;
; Macros for Error-LED-Out (Active low)
;
.MACRO LedErrOn
CBI PortB,bFail
.ENDM
.MACRO LedErrOff
SBI PortB,bFail
.ENDM
;
; Macros for delays
;
.MACRO Delay1 ; Single delay step
NOP
.ENDM
;
.MACRO Delay2 ; Double delay step
NOP
NOP
.ENDM
;
.MACRO Delay3 ; Delay macro for multiples of 3 steps
LDI rdel,@0
MD3:
DEC rdel
BRNE MD3
.ENDM
;
.MACRO Delay4 ; Delay Macro for multiples of 4 steps
LDI rdel,@0
MD4:
DEC rdel
NOP
BRNE MD4
.ENDM
;
.MACRO MacPwm ; Macro for Pulse Width Generator
DEC rpwc ; 1 1 1 1
BREQ MAP2 ; 1 1 2 2
CP rpws,rpwc ; 1 1
BRCS MAP1 ; 1 2
NOP ; 1
CBI PortB,bOut; 2
RJMP MAP3 ; 2
MAP1:
SBI PortB,bOut; 2
RJMP MAP3 ; 2
MAP2:
MOV rpws,rpwn ; 1 1
LDI rpwc,cstep; 1 1
SBI PortB,bOut; 2 2
NOP ; 1 1
NOP ; 1 1
MAP3: ;-----------
; 9 9 9 9
;===========
.ENDM
;
; Start of main program, Init variables
;
Start:
LDI rpwc,cDflt ; Counter of the pwm
LDI rpws,cDflt ; Current pwm value
LDI rpwn,cDflt ; Next pwg value
;
; Init the Port B
;
LDI rmpr,pbmode ; Set data direction mode
OUT DDRB,rmpr ; on Port B
SBI PortB,bIn ; Switch pull-up resistor on
;
; Start phase I : Wait until input is pulled low
;
; Set error condition until signal is correct
;
PH1:
MacPwm ; 9
LDI rerr,cFbck; 1
LDI rpwn,cDflt; 1
LedErrOn ; 2
Delay3(3) ; 9
;
; Set one cycle length for negative edge detection
;
PH1a:
LDI ZL,Low(cCycl); 1
LDI ZH,HIGH(cCycl);1
; ---
; 24
; ===
; Wait until input is pulled low or timeout occurs
;
PH1b:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH2 ; 2
SBIW ZL,1 ; 2 2
BREQ PH1c ; 1 2
Delay4(2) ; 8
RJMP PH1b ; 2
; ---
; 24
; ===
; Timed out with input high
;
PH1c: ; (15)
Delay4(1) ; 4
;
; Error occured with input high, count subsequent errors
;
PH1d: ;(19 19)
DEC rerr ; 1 1
BRNE PH1a ; 2 1
;
; Too many subsequent errors with input high, set error condition
;
Delay1 ; 1
RJMP PH1 ; 2
; ---
; 24
; ===
; Start Phase II: Input is low, wait for pulse or timeout
;
PH2: ; (12)
Delay3(2) ; 6
Delay2 ; 2
RJMP PH2b ; 2
;
; Error occured with input low, set error condition
;
PH2a:
MacPwm ; 9
LDI rerr,cFbck; 1
LDI rpwn,cDflt; 1
LedErrOn ; 2
Delay3(3) ; 9
;
; Set counter for time out during input low
;
PH2b: ; (22 22)
LDI ZL,LOW(cCycl); 1 1
LDI ZH,HIGH(cCycl); 1 1
; ------
; 24 24
; ======
; Wait until input goes high or time-out occurs
;
PH2c:
MacPwm ; 9 9 9 9
SBIC PinB,bIn ; 2 2 2 1
RJMP PH3 ; 2
SBIW ZL,1 ; 2 2 2
BREQ PH2d ; 1 2 2
Delay4(2) ; 8
RJMP PH2c ; 2
; ---
; 24
; ===
; Time out during input low, count subsequent errors
;
PH2d: ; (15 15)
Delay4(1) ; 4 4
PH2e: ; (19 19)
DEC rtry ; 1 1
BRNE PH2b ; 1 2
NOP ; 1
RJMP PH2a ; 2
; ---
; 24
; ===
; Phase III: Input gone high, check for cMin1 phases if stable
;
PH3: ; (12)
Delay3(3) ; 9
Delay2 ; 2
LDI rtry,cMin1; 1
; ---
; 24
; ===
; Wait until cMin1 phases passed with input high
;
PH3a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH3b ; 2
DEC rtry ; 1 1
BREQ PH4 ; 1 2
Delay3(3) ; 9
RJMP PH3a ; 2
; ---
; 24
; ===
; Early low detected during cMin1-phase, error with input low
;
PH3b: ; (12)
Delay3(1) ; 3
Delay2 ; 2
RJMP PH2e ; 2
;
; Phase IV: Input is high for cMin1, pre-tolerance time
;
PH4: ;(14)
Delay4(2) ; 8
LDI rtry,cTlp ; 1
LDI rctr,cstep; 1
; ---
; 24
; ===
; Wait for pre-tolerance time or input early low
;
PH4a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rtry ; 1 1
BREQ PH5 ; 1 2
Delay3(3) ; 9
RJMP PH4a ; 2
; ---
; 24
; ===
;
; Phase V: End of pre-tolerance has been reached, count down now
;
PH5: ; (14)
Delay4(2) ; 8
Delay2 ; 2
; ---
; 24
; ===
PH5a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rctr ; 1 1
BREQ PH6 ; 1 2
Delay3(3) ; 9
RJMP PH5a ; 2
; ---
; 24
; ===
; Phase VI: End of count reached, tolerate overtime
;
PH6: ; (14)
Delay3(3) ; 9
LDI rtry,cTla ; 1
; ---
; 24
; ===
; Overtime for cTla, break if overtime or input low
;
PH6a:
MacPwm ; 9 9 9
SBIS PinB,bIn ; 2 2 1
RJMP PH7 ; 2
DEC rtry ; 1 1
BREQ PH6b ; 1 2
Delay3(3) ; 9
RJMP PH6a ; 2
; ---
; 24
; ===
; Active signal too long, failure condition with input high
;
PH6b: ; (14)
Delay3(1) ; 3
RJMP PH1d ; 2
;
; Phase VII: Input inactive, check minimum inactive time
;
;
PH7: ; (12)
Delay4(2) ; 8
Delay2 ; 2
LDI ZL,LOW(cMin0); 1
LDI ZH,HIGH(cMin0); 1
; ---
; 24
; ===
PH7a:
MacPwm ; 9 9 9
SBIC PinB,bIn ; 2 2 1
RJMP PH7b ; 2
SBIW ZL,1 ; 2 2
BREQ PH7c ; 1 2
Delay4(2) ; 8
RJMP PH7a ; 2
; ---
; 24
; ===
; Early end of minimum inactive time, failure condition with input
high
;
PH7b: ; (12)
Delay3(1) ; 3
Delay2 ; 2
RJMP PH1d ; 2
;
; End of minimum inactive time reached, set result, restart with
input low
;
PH7c: ; (15)
MOV rpwn,rctr ; 1
LDI rerr,cFbck; 1
LedErrOff ; 2
Delay1 ; 1
RJMP PH2b ; 2
;
; End of the program
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/PCM2PWG4.html1/20/2009 7:57:22 PM
Decoder for remote control signals

Path: Home => AVR-Overview => Applications => PCM-Decoder

AVR-Single-Chip-Processors
AT90Sxxxx
in practical examples.

Decoder for remote control signals


1. General overview
2. Details of remote control signal encoding
3. Conversion of remote control signals to an analogue voltage
4. Required hardware
5. Program structure

General overview
The decoder converts puls-encoded remote control signals, supplied on the input pin of a AT90S2323
processor (Port-Bit 0, Pin 5), to a pulse generator on the output (Port-Bit 1, Pin 6). By filtering this
pulse generator output in a simple RC network a analogue signal results, which linearly rises with the
pulse length of the applied PCM signal on the input. The analogue signal can be fed into a
comparator and driver for remote controlled equipment like airplane models etc. If false signals are
detected or if the input signal is missing a pre-defined default value is set on the analogue output. To
detect this condition, a LED can be connected to Port-Bit 2, Pin 7, for testing purposes.
The current version of the program is predefined to detect active high PCM signals of 0.8 to 2.2 ms
duration and an overall signal length of 25 ms. The default value for the analogue output is set to be
50% (2.50 Volt) after a single failure. All parameters of the program can be re-adjusted for other
purposes and timings. Only a few commented parameters in the source code have to be re-adjusted to
fit to other timings.
HTML-Format Source-code-Format Flow chart in GIF-Format Flow chart in PDF-Format
Wiring in PDF-Format Wiring in GIF-Format

To top of this document

Details on remote control signal encoding


A remote control signal has to encode an analogue signal (e.g. a voltage sensed from a variable
resistor) to a digital signal, which can be decoded by the receiver back to the analogue signal and
drives a motor or other equipment.
The analogue signal is first encoded to a pulse signal. The duration of that pulse varies with the input
signal. If the voltage is zero, the signal is more or less exactly 0.8 ms long. If the voltage is on the
upper end of the scale, the signal is 2.2 ms long. The information of the analog voltage is encoded
into the pulse length, it is modulating the pulse length. These signals are called PCM-encoded. More
time is between this and the next pulse: two pulses are 25 ms from each other, 40 pulses fit into one
second and so a frequency of 40 Hz results. The pulse-encoded signal is then fed into a transmitter.
This encodes the pulse a second time and modulates a high-frequency signal, which is transmitted
over the antenna. A HF receiver decodes the received signal again and its output is the same PCM-
encoded signal that we modulated on the HF.

To top of this document

Conversion to an analogue signal


The pure PCM-encoded signal has to be converted first to be used further on. This stage is what the
AT90S2323 is doing: he counts the length of the pulse, between 0.8 and 2.2 ms, and converts it to
pulse width signal on the output. There are many other ways to do this, but these are more or less
convenient and reliable. We leave the counting to a micro.
The small AT90S2323 is clocked by a crystal oscillator, so he knows exactly what time it is. The
only things he has to do is counting: the length of the input signal and the length of the output signal.
Easy, but looking at the program below, the clock signal has to fit exactly. The AT90S2323 has no
pulse width generator, so we do have to do this counting by software.
Switching the pulse width generator on and off is smoothed by the external RC network, so a very
smooth output signal results.

To top of this document

Required hardware
The required hardware is very lean (the PDF-file).

The Xtal is responsable for the whole timing of the processor, the two capacitors improve the
oscillator reliablility. The RC combination on pin 1 provides the Reset signal for the processor.
The PCM-encoded input signal is connected to pin 5 of the processor. The PWG output loads and
unloads the capacitor and is smoothed by the resistor on the output pin 6. The error LED is connected
to pin 7 and only required for testing purposes.

To top of this document

Program structure
The whole software is sensitive to the timing and does not use interrupts or subroutine calls.
HTML-Format Source-Code-Format Flow chart in GIF-Format Flow chart in PDF-Format
The duration of the pulse is counted in 233 single loop steps, each 6 microseconds long. That covers
the 1.4 ms of the longest pulse. Pulses that are a little bit shorter than 0.8 ms or a little bit longer than
2.2 ms are tolerated by use of extra counting loops and do not set an error condition. Pulse with a
very short (0,8 ms - 10%) or a very long duration (2.2 ms + 10%), pulses followed with less than the
required inactive time, or missing pulses after a certain time-out set such an error condition.
Subsequent errors are counted down. Reaching zero sets the error LED on and sets the PWG to the
pre-defined default value, in our case 50% pulse width or 2.5 Volts.
The pulse width generator is in the current version clocked with 1.4 ms pulses, a frequency of around
714 Hrz results. Accuracy of the signal counting and the PWG is below 0.5% and hence good enough
for serious applications.

To top of this document

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/REMOTE.html1/20/2009 7:57:23 PM
http://www.avr-asm-tutorial.net/avr_en/source/PCM2PWG4.asm

; *******************************************************************
; * PCM2PWG-Decoder for AT90S2323, Version 0.4 as of 20.12.2000 *
; * Translates pulse coded input to Pulse Width Generator Output *
; * (C)2000 by info@avr-asm-tutorial.net *
; *******************************************************************
;
; Currently adjusted for 800 to 2200 µs signals and 4 MHz.
; Adjust constants below to fit to other timings!
;
; VCC LED PWG PCM PCM-Inp: 25ms = 40 Hz cycle time
; Out Out Inp active high pulse encoded signal
; +-8----7----6----5--+
; | | PWG-Out: 1.4 ms = 714 Hz cycle time
; O AT 90 S 2323 | active high for 0..1.4 ms
; | |
; +-1----2----3----4--+ LED-Out: Active low if error occurs
; RST XT1 XT2 GND
;
; ********* Input Signal PCM encoded **************************
;
; Phase I II III IV V VI VII
; PCM 1---- -------------------- ------
; Inp \\\\\ / \\\\\\\\\\\\ /
; 0------------ ------------------------
;
; ********* Output Signal Pulse Width Generator ***************
;
; PWG 1 ------------- ------
; Out / \ /
; 0---- -------------
; Time µs |<--0..cCycl->|<-cCycl..0-->| 800 - 2200 µs:
; |<----------cCycl---------->| cCycl = 1400 µs
;
; *************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\2323def.inc"
.LIST
;
; Used registers
;
.DEF rmpr = R16 ; Multi Purpose register
.DEF rdel = R17 ; Register for delay loops
.DEF rpwc = R18 ; Counter for pulse width generator
.DEF rpws = R19 ; Current setting of pulse width generator
.DEF rpwn = R20 ; Next setting of the pulse width generator
.DEF rtry = R21 ; Number of retries
.DEF rctr = R22 ; Counter for active cycles
.DEF rerr = R23 ; Number of failures
; ZL = R30 and ZH = R31 used for counting long times
;
; IO-Port-Bits
;
.EQU pbmode = 0b00000110 ; Port B Output pins
.EQU bIn = 0 ; Input pin is 0, active high
.EQU bOut = 1 ; Output pin for PWG, pulse width generator
.EQU bFail = 2 ; Output pin for failure LED, active low
;
; Constants (1 cycle = 6 µs = 24 clock cycles @ 4 MHz)
;
; Adjust the xtal frequency for other clocks
;
.EQU cXtal = 4 ; Crystal frequency in MHz
;
; Adjust this cycle length for other total lengthes of the input signal
;
.EQU cPulseDuration = 25000 ; Total pulse length in µs
;
; Adjust the timing for other active high encoder pulses
;
.EQU cMinPulse = 800 ; Minimum pulse length in µs
.EQU cMaxPulse = 2200 ; Maximum pulse length in µs
;
; Adjust this fallback value in % of total duration if errors or
; signal-losses occur, 0%: Output is low, 100%: output is high,
; 50%: Output is 50% pulse width
;
.EQU cFallBackValue = 50 ; 50% pulse width
;
; The following are automatically calculated from the above,
; don't adjust these without knowing what you do!
;
.EQU cUnitLength = 24 ; Clock cycles per unit loop
.EQU cCycleLength = cUnitLength/cXtal ; Total cycle length in µs
.EQU cCycl = cPulseDuration/cCycleLength ; Cycles in 25 ms
.EQU cStep = (cMaxPulse-cMinPulse)/cCycleLength ; Active cycles
.EQU cTolerance = cStep/10; Tolerated short/long signal length
.EQU cMinSteps = cMinPulse/cCycleLength ; Start counting active pulse
.EQU cMaxSteps = cMaxPulse/cCycleLength ; Stop counting active pulse
.EQU cMin1 = cMinSteps-cTolerance-1 ; Unit loops that must be active high
.EQU cTlp = cTolerance-1 ; Early low units that are tolerated as Zero
.EQU cTla = cTolerance ; Late units tolerated as One
.EQU cMin0 = (cCycl-cMaxSteps)*90/100 ; Units that must be inactive
.EQU cFbck = 1 ; Number of false signals to tolerate before default is set
.EQU cDflt = cstep*cFallbackValue/100 ; Default fallback value for PWG
;
; Macros for Error-LED-Out (Active low)
;
.MACRO LedErrOn
cbi PortB,bFail
.ENDM
.MACRO LedErrOff
sbi PortB,bFail
.ENDM
;
; Macros for delays
;
.MACRO Delay1 ; Single delay step
nop
.ENDM
;
.MACRO Delay2 ; Double delay step
nop
nop
.ENDM
;
.MACRO Delay3 ; Delay macro for multiples of 3 steps
ldi rdel,@0
MD3:
dec rdel
brne MD3
.ENDM
;
.MACRO Delay4 ; Delay Macro for multiples of 4 steps
ldi rdel,@0
MD4:
dec rdel
nop
brne MD4
.ENDM
;
.MACRO MacPwm ; Macro for Pulse Width Generator
dec rpwc ; 1 1 1 1
breq MAP2 ; 1 1 2 2
cp rpws,rpwc ; 1 1
brcs MAP1 ; 1 2
nop ; 1
cbi PortB,bOut; 2
rjmp MAP3 ; 2
MAP1:
sbi PortB,bOut; 2
rjmp MAP3 ; 2
MAP2:
mov rpws,rpwn ; 1 1
ldi rpwc,cstep; 1 1
sbi PortB,bOut; 2 2
nop ; 1 1
nop ; 1 1
MAP3:
;-----------
;9999
;===========
.ENDM
;
; Start of main program, Init variables
;
Start:
ldi rpwc,cDflt ; Counter of the pwm
ldi rpws,cDflt ; Current pwm value
ldi rpwn,cDflt ; Next pwg value
;
; Init the Port B
;
ldi rmpr,pbmode ; Set data direction mode
out DDRB,rmpr ; on Port B
sbi PortB,bIn ; Switch pull-up resistor on
;
; Start phase I : Wait until input is pulled low
;
; Set error condition until signal is correct
;
PH1:
macpwm ; 9
ldi rerr,cFbck; 1
ldi rpwn,cDflt; 1
lederron ; 2
delay3(3) ; 9
;
; Set one cycle length for negative edge detection
;
PH1a:
ldi ZL,Low(cCycl); 1
ldi ZH,HIGH(cCycl);1
; ---
; 24
; ===
; Wait until input is pulled low or timeout occurs
;
PH1b:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH2 ; 2
sbiw ZL,1 ; 2 2
breq PH1c ; 1 2
delay4(2) ; 8
rjmp PH1b ; 2
; ---
; 24
; ===
; Timed out with input high
;
PH1c:
; (15)
delay4(1) ; 4
;
; Error occured with input high, count subsequent errors
;
PH1d:
;(19 19)
dec rerr ; 1 1
brne PH1a ; 2 1
;
; Too many subsequent errors with input high, set error condition
;
delay1 ; 1
rjmp PH1 ; 2
; ---
; 24
; ===
; Start Phase II: Input is low, wait for pulse or timeout
;
PH2:
; (12)
delay3(2) ; 6
delay2 ; 2
rjmp PH2b ; 2
;
; Error occured with input low, set error condition
;
PH2a:
macpwm ; 9
ldi rerr,cFbck; 1
ldi rpwn,cDflt; 1
lederron ; 2
delay3(3) ; 9
;
; Set counter for time out during input low
;
PH2b:
; (22 22)
ldi ZL,LOW(cCycl); 1 1
ldi ZH,HIGH(cCycl); 1 1
; ------
; 24 24
; ======
; Wait until input goes high or time-out occurs
;
PH2c:
macpwm ; 9 9 9 9
sbic PinB,bIn ; 2 2 2 1
rjmp PH3 ; 2
sbiw ZL,1 ; 2 2 2
breq PH2d ; 1 2 2
delay4(2) ; 8
rjmp PH2c ; 2
; ---
; 24
; ===
; Time out during input low, count subsequent errors
;
PH2d:
; (15 15)
delay4(1) ; 4 4
PH2e:
; (19 19)
dec rtry ; 1 1
brne PH2b ; 1 2
nop ; 1
rjmp PH2a ; 2
; ---
; 24
; ===
; Phase III: Input gone high, check for cMin1 phases if stable
;
PH3:
; (12)
delay3(3) ; 9
delay2 ; 2
ldi rtry,cMin1; 1
; ---
; 24
; ===
; Wait until cMin1 phases passed with input high
;
PH3a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH3b ; 2
dec rtry ; 1 1
breq PH4 ; 1 2
delay3(3) ; 9
rjmp PH3a ; 2
; ---
; 24
; ===
; Early low detected during cMin1-phase, error with input low
;
PH3b:
; (12)
delay3(1) ; 3
delay2 ; 2
rjmp PH2e ; 2
;
; Phase IV: Input is high for cMin1, pre-tolerance time
;
PH4:
;(14)
delay4(2) ; 8
ldi rtry,cTlp ; 1
ldi rctr,cstep; 1
; ---
; 24
; ===
; Wait for pre-tolerance time or input early low
;
PH4a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rtry ; 1 1
breq PH5 ; 1 2
delay3(3) ; 9
rjmp PH4a ; 2
; ---
; 24
; ===
;
; Phase V: End of pre-tolerance has been reached, count down now
;
PH5:
; (14)
delay4(2) ; 8
delay2 ; 2
; ---
; 24
; ===
PH5a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rctr ; 1 1
breq PH6 ; 1 2
delay3(3) ; 9
rjmp PH5a ; 2
; ---
; 24
; ===
; Phase VI: End of count reached, tolerate overtime
;
PH6:
; (14)
delay3(3) ; 9
ldi rtry,cTla ; 1
; ---
; 24
; ===
; Overtime for cTla, break if overtime or input low
;
PH6a:
macpwm ; 9 9 9
sbis PinB,bIn ; 2 2 1
rjmp PH7 ; 2
dec rtry ; 1 1
breq PH6b ; 1 2
delay3(3) ; 9
rjmp PH6a ; 2
; ---
; 24
; ===
; Active signal too long, failure condition with input high
;
PH6b:
; (14)
delay3(1) ; 3
rjmp PH1d ; 2
;
; Phase VII: Input inactive, check minimum inactive time
;
;
PH7:
; (12)
delay4(2) ; 8
delay2 ; 2
ldi ZL,LOW(cMin0); 1
ldi ZH,HIGH(cMin0); 1
; ---
; 24
; ===
PH7a:
macpwm ; 9 9 9
sbic PinB,bIn ; 2 2 1
rjmp PH7b ; 2
sbiw ZL,1 ; 2 2
breq PH7c ; 1 2
delay4(2) ; 8
rjmp PH7a ; 2
; ---
; 24
; ===
; Early end of minimum inactive time, failure condition with input high
;
PH7b:
; (12)
delay3(1) ; 3
delay2 ; 2
rjmp PH1d ; 2
;
; End of minimum inactive time reached, set result, restart with input low
;
PH7c:
; (15)
mov rpwn,rctr ; 1
ldi rerr,cFbck; 1
lederroff ; 2
delay1 ; 1
rjmp PH2b ; 2
;
; End of the program
;

http://www.avr-asm-tutorial.net/avr_en/source/PCM2PWG4.asm1/20/2009 7:57:25 PM
Terminal controled signal generator

Path: Home => AVR-Overview => Applications => Signal generator => Source code

; **************************************************************
; * Pulse Width Generator, programmable via Serial I/O 9k6 8N1 *
; * Input cycle length in µs first, then active cycle in µs *
; * Default cycle length is 25,000 µs, default active cycle is *
; * 2,000 µs. Output is on Port D, Bit 2 *
; * Written for the STK200 board, AT90S8515 *
; * (C)2000 by info!at!avr-asm-tutorial, error reports welcome *
; **************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Used registers
;
.DEF rlpm=R0; Used for LPM commands
.DEF rchar=R1; Character buffer for SIO communications
.DEF rilo=R2; Low byte word input/active loop
.DEF rihi=R3; High byte word input/active loop
.DEF rjlo=R4; Low byte for multiplication/inactive loop
.DEF rjhi=R5; High byte for multiplication/inactive loop
;
.DEF rmpr=R16; A multipurpose register, byte/word
.DEF rcl=R18; Desired cycle time, word
.DEF rch=R19
.DEF ral=R20; Desired active time, word
.DEF rah=R21
; X=R26/27: Counter for Active time
; Y=R28/29: Counter for inactive time
; Z=R30/31: Pointer for program memory read operation
;
; Constants
;
.EQU OutPort=PortD; Desired output port
.EQU DataDir=DDRD; Data direction register of that port
.EQU ActivePin=2; Desired output pin
.EQU ModeControl=0b00000100; Control word for port
.EQU cDefCyc=25000; Default cycle length in µs
.EQU cDefAct=2000; Default active high length in µs
.EQU fq=4000000; Xtal frequency on board in Hz
.EQU baud=9600; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cbel=0x07; Bell character
;
; Macro Check input value for default and transfer to desired
register
;
.MACRO Default
MOV @0,rilo; Copy result to desired register pair
MOV @1,rihi
MOV rmpr,rilo; Test if input is zero
OR rmpr,rihi
BRNE nodef; Not zero, don't set default value
LDI @0,LOW(@2); Set to default value
LDI @1,HIGH(@2)
nodef:
.ENDM
;
; Code segment start
;
.CSEG
;
; Reset- and interrupt-vectors, interrupts not used here
;
RJMP Start; Reset vector
RETI; Ext Int 0
RETI; Ext Int 1
RETI; Timer 1 Capt
RETI; Timer 1 CompA
RETI; Timer 1 CompB
RETI; Timer 1 OVF
RETI; Timer 0 OVF
RETI; Serial Transfer Complete
RETI; UART Rx Complete
RETI; UART Data register empty
RETI; UART Tx Complete
RETI; Analog Comparator
;
; Subroutine for string transmit
;
TxStr:
SBIS USR,UDRE; Wait until transmit buffer empty
RJMP TxStr
LPM; Read next character from program memory
AND rlpm,rlpm; NUL = end of string
BRNE txsend
RET
txsend:
LPM; Read the same char again
OUT UDR,rlpm; Tx character read
ADIW ZL,1; point to next char im memory
RJMP TxStr
;
; Subroutine for receiving a number (word, 0..65535)
;
RxWord:
CLR rilo; Set buffer to zero
CLR rihi
rxw1:
SBIS USR,RXC; Test if rx buffer empty
RJMP rxw1; receive char not available, repeat
IN rmpr,UDR; Get the char from the SIO
OUT UDR,rmpr; Echo this character
CPI rmpr,ccr; Return char = end of input
BREQ rxwx
SUBI rmpr,'0'; Subtract 48
BRCS rxwerr; not a decimal number, return wit carry set
CPI rmpr,10; number >9?
BRCS rxwok; legal decimal number
rxwerr:
LDI ZL,LOW(2*ErrorStr); Echo error string
LDI ZH,HIGH(2*ErrorStr)
RCALL TxStr
SEC; Set carry flag, not a legal number
RET
rxwok:
MOV rjlo,rilo; Copy word for multiplicaton
MOV rjhi,rihi
LSL rilo; Multiply with 2 = 2*
ROL rihi
BRCS rxwerr; Overflow, return with carry set
LSL rilo; Multiply again by 2, = 4*
ROL rihi
BRCS rxwerr; Overflow, return with carry set
ADD rilo,rjlo; Add copy, = 5*
ADC rihi,rjhi
BRCS rxwerr; Overflow, return with carry set
LSL rilo; Multiply by 2, = 10*
ROL rihi
BRCS rxwerr; Overflow, return with carry set
CLR rjhi; Add the decimal number
ADD rilo,rmpr
ADC rihi,rjhi
BRCS rxwerr; Overflow, return with carry set
RJMP rxw1; Get next character
rxwx:
SBIS USR,UDRE; Wait until transmit buffer empty
RJMP rxwx
LDI rmpr,clf; Transmit additional line feed char
OUT UDR,rmpr
CLC; Clear carry, no errors
RET
;
; Start of program
;
Start:
;
; Setup the stack for the use of subroutines
;
LDI rmpr,HIGH(RAMEND); Stack setting to highest RAM adress
OUT SPH,rmpr
LDI rmpr,LOW(RAMEND)
OUT SPL,rmpr
;
; Initiate Port D to output on Bit 2
;
LDI rmpr,ModeControl; Set output pin
OUT DataDir,rmpr; to Data Direction register
;
; Initiate SIO communication
;
LDI rmpr,bddiv; Set baud rate
OUT UBRR,rmpr
LDI rmpr,0b00011000; Enable TX and RX
OUT UCR,rmpr
;
; Transmit the hello sequence
;
hello:
LDI ZH,HIGH(2*InitStr); Point Z to string
LDI ZL,LOW(2*InitStr)
RCALL TxStr
;
; Get value for total cycle length
;
getcycle:
LDI ZH,HIGH(2*CycleStr); Point Z to string
LDI ZL,LOW(2*CycleStr)
RCALL TxStr
RCALL RxWord
BRCS getcycle; Repeat if error
Default rcl,rch,cDefCyc
;
; Get value for active cycle length
;
getactive:
LDI ZH,HIGH(2*ActiveStr); Point Z to string
LDI ZL,LOW(2*ActiveStr)
RCALL TxStr
RCALL RxWord
BRCS getactive; Repeat if error
Default ral,rah,cDefAct
;
; Calculate counter value for active time
;
MOV XL,ral; Calculate active time
MOV XH,rah
SBIW XL,5; at least 4 cycles
BRCS getcycle; illegal active time
ADIW XL,1; At least one cycle required
MOV rilo,XL
MOV rihi,XH
;
; Calculate counter value for inactive time
;
MOV YL,rcl; Calculate inactive time
MOV YH,rch
SUB YL,XL; Subtract active time
SBC YH,XH
BRCS getcycle; Active time longer than cycle time
SBIW YL,5; Subtract loop delays
BRCS getcycle; Less than 3 loop cycles are illegal
ADIW YL,1; minimum 1 loop
MOV rjlo,YL
MOV rjhi,YH
LDI ZH,HIGH(2*WaitStr); Output operating string
LDI ZL,LOW(2*WaitStr)
RCALL TxStr
;
; Counting loop starts here, check char at SIO available?
;
ctloop:
SBI OutPort,ActivePin; Start active phase
ActLoop:
SBIW XL,1; 0.5 µs
BRNE ActLoop; 0.5 µs
SBIC USR,RXC; Test if rx buffer empty
RJMP getcycle; get new cycle time
CBI Outport,ActivePin; Start Inactive phase
InactLoop:
SBIW YL,1; 0.5 µs
BRNE InactLoop; 0.5 µs
MOV XL,rilo; Refresh counters
MOV XH,rihi
MOV YL,rjlo
MOV YH,rjhi
NOP
NOP
RJMP ctloop; start a new cycle
;
; Text strings for transmit, ANSI screen encoded!
;
ErrorStr:
.DB cbel,ccr,clf,cesc,'[','3','3','m'
.DB "Error in input! Repeat input! "
.DB ccr,clf,cnul,cnul
ActiveStr:
.DB cesc,'[','3','2','m','*'
.DB "Input active time (default = 2,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
CycleStr:
.DB cesc,'[','3','2','m','*'
.DB "Input cycle time (default = 25,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
WaitStr:
.DB cesc,'[','3','5','m','C'
.DB "ontinued operation. "
.DB ccr,clf,cesc,'[','3','7','m','E'
.DB "nter new cycle length to stop and restart generator."
.DB ccr,clf,cnul,cnul
InitStr:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Set screen
colours
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB ccr,clf,ccr,clf
.DB "Hello world!"
.DB ccr,clf
.DB "This is the pulse width generator at work."
.DB ccr,clf
.DB "All times in micro-seconds, accepted range 5..65535."
.DB ccr,clf
.DB "New value stops operation until all input is completed. "
.DB ccr,clf,cnul,cnul
;
Check:
.DW check
;
; End of code segment
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/PWGSIO2.html1/20/2009 7:57:29 PM
Terminal controled signal generator

Path: Home => AVR-Overview => Applications => Signal generator

AVR-Single-Chip-Processor
AT90Sxxxx
of ATMEL in practical examples.

ANSI-terminal programmable signal generator


This application provides a pulse generator for signals from 5 microseconds to 65,535 microseconds
length and selectable high/low pulse length of any combination. The duration of the signal and the
active high period duration are programmable providing these numbers (in microseconds) with an
ANSI-compatible terminal program to the STK200 via the board's SIO connection.

This application requires:

● the STK200 board with a AT90S8515 on board; or alternatively: a 2313 with a SIO interface
(re-adjustment of some parts of the source code is also required then!),
● a computer with a RS232 interface and an ANSI-compatible terminal program (like
HyperTerminal for Windows),
● connecting the computer's SIO interface with the board's interface (with at least a two-wire
connection).

Usage:

1. Start your terminal program and set the required parameters: COM x, 9600 Baud, 8 bits data,
No parity, 1 stop-bit
2. Switch the board on; your terminal should turn to black background and show the welcome
message,
3. Input the total length of the pulses in microseconds (5 to 65535) and press return,
4. Input the length of the active high part of the pulse in microseconds (5 to 65534) and press
return,
5. Watch Port D, Bit 2 for the pulses!

Code in HTML-Format Source code as .asm

Warning:

● Changing the source code in the string area at the end of the code (from Label 'ErrorStr'
downwards) can yield strange results due to two different serious compiler bugs!
● Strings always have to have an even number of chars!
● The number of byte or char constants on one line has also to be even!
● Don't mix Strings and byte or char constants on one line! Always place them in extra lines!
● Watch the list output of the compiler for messages stating "Garbage at end of line!". It is not a
fatal error causing a break, but all labels behind this line might be corrupt!
● Compare the label 'Check' on the end of the compiler listing. If it points exactly to itself
anything is ok with the strings. If it doesn't point to itself you sure ran into that bug and your
terminal output and all following labels will be corrupted.
● While the above points result in erroneous label adresses the use of semicolons in strings
causes another compiler bug: he ignores the part of the string behind that char on the same
line. That bug is not easy to find, so either avoid the use of that char or place it as hex byte on
an extra line, together with another char.
● The golden rule of string programming: ALWAYS place strings behind the end of your
executable code. Otherwise you risk jumps to false labels and your AVR might do interesting
things with the false code.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/PWG.html1/20/2009 7:57:32 PM
http://www.avr-asm-tutorial.net/avr_en/source/PWGSIO2.asm

; **************************************************************
; * Pulse Width Generator, programmable via Serial I/O 9k6 8N1 *
; * Input cycle length in µs first, then active cycle in µs *
; * Default cycle length is 25,000 µs, default active cycle is *
; * 2,000 µs. Output is on Port D, Bit 2 *
; * Written for the STK200 board, AT90S8515 *
; * (C)2000 by info@avr-asm-tutorial.net, error reports welcome*
; **************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Used registers
;
.DEF rlpm=R0; Used for LPM commands
.DEF rchar=R1; Character buffer for SIO communications
.DEF rilo=R2; Low byte word input/active loop
.DEF rihi=R3; High byte word input/active loop
.DEF rjlo=R4; Low byte for multiplication/inactive loop
.DEF rjhi=R5; High byte for multiplication/inactive loop
;
.DEF rmpr=R16; A multipurpose register, byte/word
.DEF rcl=R18; Desired cycle time, word
.DEF rch=R19
.DEF ral=R20; Desired active time, word
.DEF rah=R21
; X=R26/27: Counter for Active time
; Y=R28/29: Counter for inactive time
; Z=R30/31: Pointer for program memory read operation
;
; Constants
;
.EQU OutPort=PortD; Desired output port
.EQU DataDir=DDRD; Data direction register of that port
.EQU ActivePin=2; Desired output pin
.EQU ModeControl=0b00000100; Control word for port
.EQU cDefCyc=25000; Default cycle length in µs
.EQU cDefAct=2000; Default active high length in µs
.EQU fq=4000000; Xtal frequency on board in Hz
.EQU baud=9600; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.EQU ccr=0x0D; Carriage return character
.EQU clf=0x0A; Line feed character
.EQU cnul=0x00; NUL character
.EQU cesc=0x1B; ESCAPE character
.EQU cbel=0x07; Bell character
;
; Macro Check input value for default and transfer to desired register
;
.MACRO Default
mov @0,rilo; Copy result to desired register pair
mov @1,rihi
mov rmpr,rilo; Test if input is zero
or rmpr,rihi
brne nodef; Not zero, don't set default value
ldi @0,LOW(@2); Set to default value
ldi @1,HIGH(@2)
nodef:
.ENDM
;
; Code segment start
;
.CSEG
;
; Reset- and interrupt-vectors, interrupts not used here
;
rjmp Start; Reset vector
reti; Ext Int 0
reti; Ext Int 1
reti; Timer 1 Capt
reti; Timer 1 CompA
reti; Timer 1 CompB
reti; Timer 1 OVF
reti; Timer 0 OVF
reti; Serial Transfer Complete
reti; UART Rx Complete
reti; UART Data register empty
reti; UART Tx Complete
reti; Analog Comparator
;
; Subroutine for string transmit
;
TxStr:
sbis USR,UDRE; Wait until transmit buffer empty
rjmp TxStr
lpm; Read next character from program memory
and rlpm,rlpm; NUL = end of string
brne txsend
ret
txsend:
lpm; Read the same char again
out UDR,rlpm; Tx character read
adiw ZL,1; point to next char im memory
rjmp TxStr
;
; Subroutine for receiving a number (word, 0..65535)
;
RxWord:
clr rilo; Set buffer to zero
clr rihi
rxw1:
sbis USR,RXC; Test if rx buffer empty
rjmp rxw1; receive char not available, repeat
in rmpr,UDR; Get the char from the SIO
out UDR,rmpr; Echo this character
cpi rmpr,ccr; Return char = end of input
breq rxwx
subi rmpr,'0'; Subtract 48
brcs rxwerr; not a decimal number, return wit carry set
cpi rmpr,10; number >9?
brcs rxwok; legal decimal number
rxwerr:
ldi ZL,LOW(2*ErrorStr); Echo error string
ldi ZH,HIGH(2*ErrorStr)
rcall TxStr
sec; Set carry flag, not a legal number
ret
rxwok:
mov rjlo,rilo; Copy word for multiplicaton
mov rjhi,rihi
lsl rilo; Multiply with 2 = 2*
rol rihi
brcs rxwerr; Overflow, return with carry set
lsl rilo; Multiply again by 2, = 4*
rol rihi
brcs rxwerr; Overflow, return with carry set
add rilo,rjlo; Add copy, = 5*
adc rihi,rjhi
brcs rxwerr; Overflow, return with carry set
lsl rilo; Multiply by 2, = 10*
rol rihi
brcs rxwerr; Overflow, return with carry set
clr rjhi; Add the decimal number
add rilo,rmpr
adc rihi,rjhi
brcs rxwerr; Overflow, return with carry set
rjmp rxw1; Get next character
rxwx:
sbis USR,UDRE; Wait until transmit buffer empty
rjmp rxwx
ldi rmpr,clf; Transmit additional line feed char
out UDR,rmpr
clc; Clear carry, no errors
ret
;
; Start of program
;
Start:
;
; Setup the stack for the use of subroutines
;
ldi rmpr,HIGH(RAMEND); Stack setting to highest RAM adress
out SPH,rmpr
ldi rmpr,LOW(RAMEND)
out SPL,rmpr
;
; Initiate Port D to output on Bit 2
;
ldi rmpr,ModeControl; Set output pin
out DataDir,rmpr; to Data Direction register
;
; Initiate SIO communication
;
ldi rmpr,bddiv; Set baud rate
out UBRR,rmpr
ldi rmpr,0b00011000; Enable TX and RX
out UCR,rmpr
;
; Transmit the hello sequence
;
hello:
ldi ZH,HIGH(2*InitStr); Point Z to string
ldi ZL,LOW(2*InitStr)
rcall TxStr
;
; Get value for total cycle length
;
getcycle:
ldi ZH,HIGH(2*CycleStr); Point Z to string
ldi ZL,LOW(2*CycleStr)
rcall TxStr
rcall RxWord
brcs getcycle; Repeat if error
default rcl,rch,cDefCyc
;
; Get value for active cycle length
;
getactive:
ldi ZH,HIGH(2*ActiveStr); Point Z to string
ldi ZL,LOW(2*ActiveStr)
rcall TxStr
rcall RxWord
brcs getactive; Repeat if error
default ral,rah,cDefAct
;
; Calculate counter value for active time
;
mov XL,ral; Calculate active time
mov XH,rah
sbiw XL,5; at least 4 cycles
brcs getcycle; illegal active time
adiw XL,1; At least one cycle required
mov rilo,XL
mov rihi,XH
;
; Calculate counter value for inactive time
;
mov YL,rcl; Calculate inactive time
mov YH,rch
sub YL,XL; Subtract active time
sbc YH,XH
brcs getcycle; Active time longer than cycle time
sbiw YL,5; Subtract loop delays
brcs getcycle; Less than 3 loop cycles are illegal
adiw YL,1; minimum 1 loop
mov rjlo,YL
mov rjhi,YH
ldi ZH,HIGH(2*WaitStr); Output operating string
ldi ZL,LOW(2*WaitStr)
rcall TxStr
;
; Counting loop starts here, check char at SIO available?
;
ctloop:
sbi OutPort,ActivePin; Start active phase
ActLoop:
sbiw XL,1; 0.5 µs
brne ActLoop; 0.5 µs
sbic USR,RXC; Test if rx buffer empty
rjmp getcycle; get new cycle time
cbi Outport,ActivePin; Start Inactive phase
InactLoop:
sbiw YL,1; 0.5 µs
brne InactLoop; 0.5 µs
mov XL,rilo; Refresh counters
mov XH,rihi
mov YL,rjlo
mov YH,rjhi
nop
nop
rjmp ctloop; start a new cycle
;
; Text strings for transmit, ANSI screen encoded!
;
ErrorStr:
.DB cbel,ccr,clf,cesc,'[','3','3','m'
.DB "Error in input! Repeat input! "
.DB ccr,clf,cnul,cnul
ActiveStr:
.DB cesc,'[','3','2','m','*'
.DB "Input active time (default = 2,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
CycleStr:
.DB cesc,'[','3','2','m','*'
.DB "Input cycle time (default = 25,000):"
.DB cesc,'[','3','1','m',' '
.DB cnul,cnul
WaitStr:
.DB cesc,'[','3','5','m','C'
.DB "ontinued operation. "
.DB ccr,clf,cesc,'[','3','7','m','E'
.DB "nter new cycle length to stop and restart generator."
.DB ccr,clf,cnul,cnul
InitStr:
.DB cesc,'[','0',59,'1',59,'3','7',59,'4','0','m'; Set screen colours
.DB cesc,'[','H',cesc,'[','J' ; ANSI Clear screen
.DB ccr,clf,ccr,clf
.DB "Hello world!"
.DB ccr,clf
.DB "This is the pulse width generator at work."
.DB ccr,clf
.DB "All times in micro-seconds, accepted range 5..65535."
.DB ccr,clf
.DB "New value stops operation until all input is completed. "
.DB ccr,clf,cnul,cnul
;
Check:
.DW check
;
; End of code segment
;

http://www.avr-asm-tutorial.net/avr_en/source/PWGSIO2.asm1/20/2009 7:57:34 PM
Signal Generator ATmega8

Pfad: Home => AVR-Overview => Applications => Signal Generator => Source Main

Signal generator with


ATmega8 - Source
code Main program

;
; ***************************************************
; * Adjustable Rectangle Generator with an ATmega8 *
; * Frequency (0.25Hz..8MHz) and Pulse Width (0.00..*
; * 100.00%) variable, LCD display (selectable sing-*
; * le/dual line, 16..40 characters per line), dis- *
; * plays frequency or rounds per minute and pulse *
; * width in % *
; * Requires include files "rectgen_m8_table.inc" *
; * and "Lcd8_02WO_rec.inc" *
; * Version 1 as of April 21, 2006 *
; * (C)2006 by info!at!avr-asm-tutorial.net *
; ***************************************************
;
.NOLIST
.INCLUDE "m8def.inc"
.LIST
;
; Debug infos
;
.EQU dbgOn = 0 ; debugging on or off
.IF dbgOn
.EQU cAdc0 = 1000 ; ADC0 value
.EQU cAdc1 = 511 ; ADC1 value
.EQU cFlg = 0
;.EQU cFlg = (1<<bTime)
;.EQU cFlg = (1<<bRpm)
;.EQU cFlg = (1<<bPw)
.ENDIF
.EQU dbghx = 0 ; debug hex output on LCD
;
; Hardware
; ___________
; __ 10k/ | _
;+5V O-|__|--|RESET PC5|--O--O O--| Display Pulsewidth
; | | _ (Single line LCD only!)
; LCD D0 O--|PD0 PC4|--O--O O--| Inverse signal
; | | _
; LCD D1 O--|PD1 PC3|--O--O O--| Display RPM
; | | _
; LCD D2 O--|PD2 PC2|--O--O O--| Display Time
; | |
; LCD D3 O--|PD3 ADC1|--O 0..5V Pulse Width adjust
; | A T |
; LCD D4 O--|PD4 ADC0|--O 0..5V Freq adjust
; | mega |
; +5V O--|VCC GND|--O GND
; | 8 | 10nF
; GND O--|GND AREF|--O--||--| AREF
; | | ___ 22H/10nF
; XTAL1 O--|XTAL1 AVCC|--O--|___|--O +5V
; | |
; XTAL2 O--|XTAL2 PB5SCK|--O LCD R/W, SCK
; | |
; LCD D5 O--|PD5 PB4MISO|--O LCD RS, MISO
; | |
; LCD D6 O--|PD6 PB3MOSI|--O MOSI
; | |
; LCD D7 O--|PD7 PB2OC1B|--O Output B
; | |
; LCD E O--|PB0 PB1OC1A|--O Output A
; |____________|
;
;
; Timings
; -------
;
; TC0: prescaler = 1024, overflow interrupt, @16MHz:
; 16.384 ms, counts down from 30 to 0, if zero
; (491.52 ms) starts ADC conversion cycle
;
; ADC channels 1 and 2: conversions startet by TC0,
; clock prescaler = 128, @16MHz, first complete
; interrupt after 200 us, second interrupt after
; 104 us, ADC is diabled and complete flag is set
; after two complete conversions
;
; ADC complete: reads value for setting ICR1-CTC from
; table entry for ADC0, calculates COMPA/COMPB
; value from CTC-value and ADC1, sets TC1-ICR1
; and COMPA/COMPB values, updates TC1-prescaler
; and TC1-output-polarity-modes
;
; TC1: Fast PWM mode/WGM=14, prescaler = 1..1024 (de-
; pending from selected frequency), ICR1 deter-
; mines TOP, COMPA/B determines phase modulated
; inversion of output signals
;
; **************************************************
; D E F I N I T I O N S
; **************************************************
;
; Constants
;
.EQU clock = 16000000 ; clock frequency
.EQU cDivF5 = $00 ; = clock * 100 (5 Bytes)
.EQU cDivF4 = $5F
.EQU cDivF3 = $5E
.EQU cDivF2 = $10
.EQU cDivF1 = $00
.EQU cDivU5 = $16 ; = clock * 100 * 60 (5 Bytes)
.EQU cDivU4 = $5A
.EQU cDivU3 = $0B
.EQU cDivU2 = $C0
.EQU cDivU1 = $00
.EQU cLcdLw = 24 ; Line width of the LCD
.EQU cLcdLn = 2 ; number of lines of the LCD
;.EQU cLcdMicro = $E4 ; micro character on LCD, doesn't work on
L2432
.EQU cLcdMicro = 'u'
.EQU cEn = 1 ; english or german version
;
; Dependant constants
;
.EQU cTMult = (256000000/clock)*100
.IF cEn
.EQU c1000s = $2C ; komma
.EQU cDecs = $2E ; dot
.ELSE
.EQU c1000s = $2E ; dot
.EQU cDecs = $2C ; komma
.ENDIF
;
; Registers
;
; used: R0..R13 for calculations
; free: R14
.DEF rSreg = R15 ; Status save register
.DEF rmp = R16 ; Multipurpose register outside Ints
.DEF rimp = R17 ; Multipurpose register inside Ints
.DEF rFlg = R18 ; flag register
.EQU bTime = 0 ; display time instead of frequency
.EQU bRpm = 1 ; display RPM instead of frequency
.EQU bInv = 2 ; invert the output signal
.EQU bAdc0 = 3 ; ADC channel 0 complete flag
.EQU bAdc1 = 4 ; ADC channel 1 complete flag
.IF cLcdLn==1
.EQU bPw = 7 ; display Pulsewidth on line 1 of
single line LCD
.ENDIF
.DEF rAdc0L = R19 ; LSB last ADC0 result
.DEF rAdc0H = R20 ; dto., MSB
.DEF rAdc1L = R21 ; LSB last ADC1 result
.DEF rAdc1H = R22 ; dto., MSB
.DEF rAdcC = R23 ; counter for delaying ADC start cycle
; free: R24..R25
; used: X (R27:R26) for calculations
; free: Y (R29:R28)
; used: Z (R31:R30) for calculations
;
; Ports
;
; LCD-Ports
.EQU pLcdData = PORTD
.EQU pLcdCtrl = PORTB
.EQU pbLcdE = 0
.EQU pbLcdRs = 4
.EQU pbLcdRw = 5
; Key Ports
.EQU pSwtchOut = PORTC
.EQU pSwtchIn = PINC
.EQU pbTime = 2
.EQU pbRpm = 3
.EQU pbInv = 4
.EQU pbPwm = 5
; Signal outputs
.EQU pSignOut = PORTB
.EQU pSignDdr = DDRB
.EQU pbSignA = 1
.EQU pbSignB = 2
;
; SRAM positions
;
.DSEG
.ORG $0060
sCtc: ; CTC divider TC1
.BYTE 2
sCmp: ; COMPA/B pulse width TC1
.BYTE 2
sPre: ; Prescaler TC1
.BYTE 1
sMode: ; mode TC1
.BYTE 1
sLcdL1: ; Line 1 of the LCD
.BYTE cLcdLw
.IF cLcdLn>1
sLcdL2: ; Line 2 of the LCD
.BYTE cLcdLw
.ENDIF
;
; **************************************************
; R E S E T - and I N T - V E C T O R S
; **************************************************
;
; Code segment
.CSEG
.ORG $0000
;
rjmp main ; Reset vector, jump to main loop
reti ; INT0, not used
reti ; INT1, not used
reti ; TIMER2COMP, not used
reti ; TIMER2OVF, not used
reti ; TIMER1CAPT, not used
reti ; TIMER1COMPA, not used
reti ; TIMER1COMPB, not used
reti ; TIMER1OVF
rjmp TC0OvflwInt ; TIMER0OVF
reti ; SPI, STC, not used
reti ; USART, RXC, not used
reti ; USART, UDRE, not used
reti ; USART, TXC, not used
rjmp AdcInt ; ADC
reti ; EE_RDY, not used
reti ; ANA_COMP, not used
reti ; TWI, not used
reti ; SPM_RDY, not used
;
; **************************************************
; I N T - V E C T O R - R O U T I N E S
; **************************************************
;
; TC0 Overflow Interrupt, starts ADC update cycle
;
TC0OvflwInt:
in rSreg,SREG ; save status
dec rAdcC ; downcount start cycle counter
brne TC0OvflwInt1
ldi rAdcC,30 ; restart counter
ldi rimp,(1<<REFS0) ; set ADMUX to channel 0
out ADMUX,rimp
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start conversion channel 0
cbr rFlg,1<<bAdc0 ; clear channel 0 complete flag
TC0OvflwInt1:
out SREG,rSreg ; restore status
reti
;
; ADC Ready Interrupt, reads ADC value
;
AdcInt:
in rSreg,SREG ; save status
sbrc rFlg,bAdc0 ; channel 0 completed?
rjmp AdcInt1 ; yes, start next channel
in rAdc0L,ADCL ; read channel 0
in rAdc0H,ADCH
ldi rimp,(1<<REFS0)|(1<<MUX0) ; set channel 1
out ADMUX,rimp
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start conversion channel 1
sbr rFlg,1<<bAdc0 ; set channel 0 complete flag
out SREG,rSreg ; restore status
reti
AdcInt1:
in rAdc1L,ADCL ; read channel 1
in rAdc1H,ADCH
ldi rimp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; disable ADC
out ADCSRA,rimp
sbr rFlg,1<<bAdc1 ; set channel 1 complete flag
out SREG,rSreg ; restore status
reti
;
; **************************************************
; S U B R O U T I N E S
; **************************************************
;
; Reads the current CTC and prescaler value and calculates
; the rate in R7:R6:R5:R4
;
GetRate:
lds rmp,sPre ; read prescaler to rmp
andi rmp,(1<<CS12)|(1<<CS11)|(1<<CS10)
breq GetRate2 ; Prescaler is zero, set carry flag
lds R4,sCtc ; read divider to R7:R6:R5:R4
lds R5,sCtc+1
clr R6
clr R7
dec rmp
breq GetRate1 ; prescaler = 1
lsl R4 ; divider * 2
rol R5
rol R6
rol R7
lsl R4 ; divider * 4
rol R5
rol R6
rol R7
lsl R4 ; divier * 8
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; prescaler = 8
lsl R4 ; divier * 16
rol R5
rol R6
rol R7
lsl R4 ; divier * 32
rol R5
rol R6
rol R7
lsl R4 ; divier * 64
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; prescaler = 64
lsl R4 ; divier * 128
rol R5
rol R6
rol R7
lsl R4 ; divier * 256
rol R5
rol R6
rol R7
dec rmp
breq GetRate1 ; prescaler = 256
lsl R4 ; divier * 512
rol R5
rol R6
rol R7
lsl R4 ; divier * 1024
rol R5
rol R6
rol R7
GetRate1: ; Timer is active, clear carry
clc
ret
GetRate2: ; Timer is inactive, set carry
sec
ret
;
; Calculate display text from current timer params
;
Calc:
sbrc rFlg,bTime ; display time?
rjmp CalcTime ; yes, move there
clr R8 ; clear division result in R11:R10:R9:R8
inc R8 ; set last bit as counter
clr R9
clr R10
clr R11
rcall GetRate
brcs L1Lcd ; Timer is off, frequency = 0
clr R3 ; set divisor in R3:R2:R1:R0:ZH:ZL:XH:XL
clr R2
clr R1
sbrc rFlg,bRpm ; display RPM?
rjmp Calc1 ; yes
ldi rmp,cDivF5 ; display frequency
mov R0,rmp
ldi ZH,cDivF4
ldi ZL,cDivF3
ldi XH,cDivF2
ldi XL,cDivF1
rjmp Calc2
Calc1:
ldi rmp,cDivU5 ; display RPM
mov R0,rmp
ldi ZH,cDivU4
ldi ZL,cDivU3
ldi XH,cDivU2
ldi XL,cDivU1
Calc2:
lsl XL ; * 2
rol XH
rol ZL
rol ZH
rol R0
rol R1
rol R2
rol R3
cp R0,R4 ; compare
cpc R1,R5
cpc R2,R6
cpc R3,R7
brcs Calc3
sub R0,R4 ; subtract
sbc R1,R5
sbc R2,R6
sbc R3,R7
sec
rjmp Calc4
Calc3:
clc
Calc4:
rol R8 ; roll result bit in
rol R9
rol R10
rol R11
brcc Calc2 ; repeat 32 times
lsl ZH ; round up?
rol R0
rol R1
rol R2
rol R3
cp R0,R4
cpc R1,R5
cpc R2,R6
cpc R3,R7
brcs Calc5
ldi rmp,1
add R8,rmp
ldi rmp,0
adc R9,rmp
adc R10,rmp
adc R11,rmp
Calc5:
;
; Display the result in R11:R10:R9:R8 on line 1
;
L1Lcd:
clr R0 ; R0 is leading blank flag
ldi ZH,HIGH(2*DecTab32) ; point to decimal table
ldi ZL,LOW(2*DecTab32)
ldi XH,HIGH(sLcdL1) ; X points to LCD line
ldi XL,LOW(sLcdL1)
ldi rmp,'F' ; display frequency
sbrc rFlg,bRpm
ldi rmp,'R' ; display RPM
sbrc rFlg,bTime
ldi rmp,'T' ; display Time
st X+,rmp ; set first char
.IF cLcdLw>16
ldi rmp,' ' ; add a blank
st X+,rmp
ldi rmp,'=' ; add =
st X+,rmp
rcall Dec32 ; write 10 millions
.ELSE
rcall Dec32 ; write ten millions
ld rmp,-X ; read char last position
cpi rmp,' ' ; is it a blank?
brne L1Lcd00
ldi rmp,'=' ; add =
st X,rmp
L1Lcd00:
adiw XL,1
.ENDIF
rcall Dec32 ; write millions
ldi rmp,c1000s
tst R0
brne L1Lcd0a
ldi rmp,' '
L1Lcd0a:
st X+,rmp
rcall Dec32 ; write 100,000's
rcall Dec32 ; write 10,000's
rcall Dec32 ; write 1,000's
ldi rmp,c1000s
tst R0
brne L1Lcd0b
ldi rmp,' '
L1Lcd0b:
st X+,rmp
rcall Dec32 ; write 100's
rcall Dec32 ; write 10's
inc R0 ; set leading blanks off
rcall Dec32 ; write 1's
tst R8 ; display decimals?
breq L1Lcd1
ldi rmp,cDecs ; set decimal char
st X+,rmp
rcall Dec32 ; write 0.1's
ldi rmp,'0'
add rmp,R8 ; write 0.01's
st X+,rmp
rjmp L1Lcd2
L1Lcd1:
ldi rmp,' ' ; set decimals blank
st X+,rmp
st X+,rmp
st X+,rmp
L1Lcd2:
.IF cLcdLw>16
ldi rmp,' ' ; add another blank
st X+,rmp
.ENDIF
sbrc rFlg,bTime ; display time?
rjmp L1Lcd4 ; yes
sbrc rFlg,bRpm ; diplay RPM?
rjmp L1Lcd3 ; yes
ldi rmp,'H' ; display frequency
st X+,rmp
ldi rmp,'z'
st X+,rmp
rjmp L1Lcd5
L1Lcd3:
ldi rmp,'p' ; display rpm
st X+,rmp
ldi rmp,'m'
st X+,rmp
rjmp L1Lcd5
L1Lcd4:
ldi rmp,cLcdMicro
st X+,rmp
ldi rmp,'s'
st X+,rmp
L1Lcd5:
.IF cLcdLw>16
ldi rmp,' '
mov R0,rmp
ldi rmp,cLcdLw-19
L1Lcd6:
st X+,R0
dec rmp
brne L1Lcd6
.ENDIF
ret
;
; Calculate next decimal digit of a 32-bit number
;
Dec32:
lpm R4,Z+ ; read next decimal number
lpm R5,Z+
lpm R6,Z+
lpm R7,Z+
clr rmp
Dec32a:
cp R8,R4 ; compare the number with the decimal digit
cpc R9,R5
cpc R10,R6
cpc R11,R7
brcs Dec32b
sub R8,R4
sbc R9,R5
sbc R10,R6
sbc R11,R7
inc rmp ; inc result
rjmp Dec32a ; repeat
Dec32b:
add R0,rmp ; add to leading blank flag
subi rmp,-'0' ; add ASCII zero
tst R0 ; still leading blanks?
brne Dec32c
ldi rmp,' ' ; set leading blank
Dec32c:
st X+,rmp ; store char in SAM buffer
ret
;
; 32 bit decimal table for conversion
;
DecTab32:
.DB $00,$CA,$9A,$3B ; 1000 mrd
.DB $00,$E1,$F5,$05 ; 100 mio
.DB $80,$96,$98,$00 ; 10 mio
.DB $40,$42,$0F,$00 ; 1 mio
.DB $A0,$86,$01,$00 ; 100,000
DecTab16:
.DB $10,$27,$00,$00 ; 10,000
.DB $E8,$03,$00,$00 ; 1,000
.DB $64,$00,$00,$00 ; 100
.DB $0A,$00,$00,$00 ; 10
;
; Calculate and display time
;
CalcTime:
rcall GetRate ; read rate to R7:R6:R5:R4
brcc CalcTime1 ; timer is active, calc time
rjmp L1Lcd ; timer is inactive, display 0
CalcTime1:
mov R2,R4 ; move multiplicator to R7:R:R5:R4:R3:R2
mov R3,R5
mov R4,R6
mov R5,R7
clr R6
clr R7
clr R8 ; clear result in R13:R12:R11:R10:R9:R8
clr R9
clr R10
clr R11
clr R12
clr R13
ldi rmp,HIGH(cTMult) ; load multiplier to R1:R0
mov R1,rmp
ldi rmp,LOW(cTMult)
mov R0,rmp
CalcTime2:
lsr R1 ; shift next bit of multiplyer to carry
ror R0
brcc CalcTime3
add R8,R2 ; add the multiplicator
adc R9,R3
adc R10,R4
adc R11,R5
adc R12,R6
adc R13,R7
CalcTime3:
lsl R2 ; multiply multiplicator by 2
rol R3
rol R4
rol R5
rol R6
rol R7
tst R0 ; check LSB for end of multiplication
brne CalcTime2
tst R1 ; check MSB for end of multiplication
brne CalcTime2
mov rmp,R8 ; keep lowest byte for rounding
mov R8,R9 ; shift result right = divide by 256
mov R9,R10
mov R10,R11
mov R11,R12
tst R13 ; check for overflow
breq CalcTime5
CalcTime4:
ldi rmp,0xFF ; overflow, set to highest number
mov R8,rmp
mov R9,rmp
mov R10,rmp
mov R11,rmp
rjmp L1Lcd ; and display
CalcTime5:
cpi rmp,0x80
brcs CalcTime6
ldi rmp,0x01 ; round up
add R8,rmp
ldi rmp,0x00
adc R9,rmp
adc R10,rmp
adc R11,rmp
brcs CalcTime4
CalcTime6:
rjmp L1Lcd
;
; Calculate pulse width, first multiply pulse duration by 10000,
; then divide the result by the total puse duration
;
CalcPw:
lds R7,sCmp ; Read active pulse duration to R10:R9:R8:R7
lds R8,sCmp+1
clr R9
clr R10
clr R0 ; clear multiplication result in R6:R5:R4:R2:R1:R0
clr R1
clr R2
clr R3
clr R4
clr R5
clr R6
ldi rmp,HIGH(10000) ; set R12:R11 to 10000
mov R12,rmp
ldi rmp,LOW(10000)
mov R11,rmp
CalcPw1:
lsr R12 ; shift next bit right to carry
ror R11
brcc CalcPw2 ; zero shifted out
add R0,R7 ; add the multiplicator
adc R1,R8
adc R2,R9
adc R3,R10
CalcPw2:
lsl R7 ; multiply by 2
rol R8
rol R9
rol R10
tst R11 ; check end of multiplication
brne CalcPw1 ; go on
tst R12
brne CalcPw1 ; go on
lds R7,sCtc ; read CTC value to R9:R8:R7
lds R8,sCtc+1
clr R9
clr R10 ; clear result of division
inc R10
clr R11
clr R12
clr R13
CalcPw3:
lsl R0 ; shift left
rol R1
rol R2
rol R3
rol R4
rol R5
rol R6
cp R4,R7 ; compare by divider
cpc R5,R8
cpc R6,R9
brcs CalcPw4 ; don't sutract
sub R4,R7
sbc R5,R8
sbc R6,R9
sec
rjmp CalcPw5 ; shift a 1 in
CalcPw4:
clc ; shift a 0 in
CalcPw5:
rol R10 ; shift result in
rol R11
rol R12
rol R13
brcc CalcPw3
lsl R3 ; round result
rol R4
rol R5
rol R6
cp R4,R7
cpc R5,R8
cpc R6,R9
brcs L2Lcd
ldi rmp,1
add R10,rmp
ldi rmp,0
adc R11,rmp
adc R12,rmp
adc R13,rmp
L2Lcd:
mov R8,R10
mov R9,R11
mov R10,R12
mov R11,R13
ldi ZH,HIGH(2*DecTab16)
ldi ZL,LOW(2*DecTab16)
clr R0
.IF cLcdLn==1
ldi XH,HIGH(sLcdL1)
ldi XL,LOW(sLcdL1)
.ELSE
ldi XH,HIGH(sLcdL2)
ldi XL,LOW(sLcdL2)
.ENDIF
ldi rmp,'P'
st X+,rmp
ldi rmp,' '
st X+,rmp
ldi rmp,'='
st X+,rmp
rcall Dec32 ; write 100's
rcall Dec32 ; write 10's
inc R0
rcall Dec32 ; write 1's
ldi rmp,cDecs ; write decimal separator
st X+,rmp
rcall Dec32 ; write 0.1's
ldi rmp,'0' ; write 0.01's
add rmp,R8
st X+,rmp
ldi rmp,'%'
st X+,rmp
ldi rmp,' '
mov R0,rmp
ldi rmp,cLcdLw-9
L2Lcd1:
st X+,R0
dec rmp
brne L2Lcd1
ret
;
; **************************************************
; U P D A T E T I M E R V A L U E S
; **************************************************
;
; Convert ADC values and set timer
;
Convert:
ldi ZH,HIGH(2*Datatable)
ldi ZL,LOW(2*Datatable)
add ZL,rAdc0L ; add ADC0 value
adc ZH,rAdc0H
add ZL,rAdc0L ; add ADC0 value again
adc ZH,rAdc0H
lpm R0,Z+ ; read table value
lpm R1,Z
sts sCtc,R0 ; copy to SRAM
sts sCtc+1,R1
clr R2 ; clear for multiplication in R3:R2:R1:R0
clr R3
mov R4,rAdc1L ; copy ADC1 result to R5:R4
mov R5,rAdc1H
clr R9 ; clear result in R9:R8:R7:R6
clr R8
clr R7
clr R6
Convert1:
lsr R5 ; shift lowest bit to carry
ror R4
brcc Convert2 ; bit is zero, don't add
add R6,R0
adc R7,R1
adc R8,R2
adc R9,R3
Convert2:
lsl R0 ; shift muliplicator one left
rol R1
rol R2
rol R3
tst R4 ; test if multiplicator is zero
brne Convert1
tst R5
brne Convert1
lsr R9 ; divide result by 2
ror R8
ror R7
lsr R9 ; divide result by 4
ror R8
ror R7
brcc Convert3
ldi rmp,1 ; round up
add R7,rmp
ldi rmp,0
adc R8,rmp
Convert3:
sts sCmp,R7 ; store in SRAM
sts sCmp+1,R8
mov ZL,rAdc0L ; copy ADC0 to Z
mov ZH,rAdc0H
ldi XL,LOW(392)
ldi XH,HIGH(392)
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS10)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS11)
ldi XL,LOW(225)
ldi XH,HIGH(225)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS10)|(1<<CS11)
ldi XL,LOW(60)
ldi XH,HIGH(60)
cp ZL,XL
cpc ZH,XH
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS12)
cpi ZL,3
brcc Convert4
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS12)|(1<<CS10)
Convert4:
sts sPre,rmp ; save to prescaler control byte storage
ldi rmp,(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)
sbis pSwtchIn,pbInv ; ask inverted
ldi rmp,(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|
(1<<WGM11)

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8_v1_main.html (1 of 2)1/20/2009 7:57:40 PM


Signal Generator ATmega8

sts sMode,rmp
ret
;
; Write the new values to TC1
;
UpdateTc1:
lds rmp,sCmp+1 ; set compare match value A
out OCR1AH,rmp
lds rmp,sCmp
out OCR1AL,rmp
lds rmp,sCmp+1 ; set compare match value B
out OCR1BH,rmp
lds rmp,sCmp
out OCR1BL,rmp
lds rmp,sCtc+1 ; set CTC value
out ICR1H,rmp
lds rmp,sCtc
out ICR1L,rmp
lds rmp,sMode ; set mode TC1
out TCCR1A,rmp
lds rmp,sPre
out TCCR1B,rmp
ret
;
; **************************************************
; L C D - R O U T I N E S
; **************************************************
;
; Init the LCD
;
InitLcd:
ldi ZH,HIGH(2*LcdInitText)
ldi ZL,LOW(2*LcdInitText)
rjmp LcdInit
;
; Display line 1 of the LCD
;
LcdL1:
ldi ZH,HIGH(sLcdL1) ; Z to line 1 in SRAM
ldi ZL,LOW(sLcdL1)
rjmp LcdLine1
;
; Display line 2 of the LCD
;
.IF cLcdLn>1
LcdL2:
ldi ZH,HIGH(sLcdL2) ; Z to line 2 in SRAM
ldi ZL,LOW(sLcdL2)
rjmp LcdLine2
.ENDIF
;
; Display TC1 parameters in hex on display line 1
;
.IF dbghx
LcdHexPar:
rcall LcdHome
lds ZH,sCtc+1
lds ZL,sCtc
rcall Displ4Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds ZH,sCmp+1
lds ZL,sCmp
rcall Displ4Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds rmp,sMode
rcall Displ2Hex
ldi rmp,' '
mov R0,rmp
rcall LcdChar
lds rmp,sPre
rcall Displ2Hex
ldi rmp,' '
mov R0,rmp
rjmp LcdChar
Displ4Hex:
mov rmp,ZH
rcall Displ2Hex
mov rmp,ZL
Displ2Hex:
push rmp
swap rmp
rcall Displ1Hex
pop rmp
Displ1Hex:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs Displ1Hex1
subi rmp,-7
Displ1Hex1:
mov R0,rmp
rjmp LcdChar
.ENDIF
;
; **************************************************
; M A I N P R O G R A M I N I T
; **************************************************
;
Main:
ldi rmp,HIGH(RAMEND) ; init stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
; init key input port
ldi rmp,(1<<pbTime)|(1<<pbRpm)|(1<<pbInv)|(1<<pbPwm)
out pSwtchOut,rmp
; Init the signal outputs
sbi pSignDdr,pbSignA
sbi pSignDdr,pbSignB
cbi pSignOut,pbSignA
sbi pSignOut,pbSignB
; init flags
clr rFlg
.IF dbgOn ; debugging math
ldi rmp,HIGH(cAdc0)
mov rAdc0H,rmp
ldi rmp,LOW(cAdc0)
mov rAdc0L,rmp
ldi rmp,HIGH(cAdc1)
mov rAdc1H,rmp
ldi rmp,LOW(cAdc1)
mov rAdc1L,rmp
ldi rFlg,cFlg
rcall Convert
rcall UpdateTc1
.IF cLcdLn>1
rcall Calc
rcall CalcPw
.ELSE
sbrc rFlg,bPw
rjmp dbgPw
rcall Calc
rjmp dbgloop
dbgPw:
rcall CalcPw
.ENDIF
dbgloop:
rjmp dbgloop
.ENDIF
; init the LCD
rcall InitLcd
; init the ADC conversion
ldi rmp,(1<<REFS0) ; set ADMUX to channel 0
out ADMUX,rmp
ldi rmp,(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; start conversion channel 0
ldi rAdcC,1 ; set start value for ADC delay
ldi rmp,(1<<CS02)|(1<<CS00) ; prescaler 1024
out TCCR0,rmp
ldi rmp,1<<TOIE0 ; enable TC0 overflow int
out TIMSK,rmp
sei
;
; **************************************************
; M A I N P R O G R A M L O O P
; **************************************************
;
Loop:
sleep
nop
sbrs rFlg,bAdc1 ; ADC ready flag set?
rjmp Loop ; no, sleep on
cbr rFlg,1<<bAdc1 ; clear ADC ready flag
.IF cLcdLn == 1
cbr rFlg,(1<<bTime)|(1<<bRpm)|(1<<bPw)|(1<<bInv)
sbis pSwtchIn,pbPwm
sbr rFlg,1<<bPw
.ELSE
cbr rFlg,(1<<bTime)|(1<<bRpm)|(1<<bInv)
.ENDIF
sbis pSwtchIn,pbInv ; inverted signals?
sbr rFlg,1<<bInv
sbis pSwtchIn,pbTime
sbr rFlg,1<<bTime
sbis pSwtchIn,pbRpm
sbr rFlg,1<<bRpm
rcall Convert ; convert ADC to TC1 values
rcall UpdateTc1
.IF cLcdLn>1
rcall Calc ; calculate frequency
rcall CalcPw ; calculate pulse width
rcall LcdL2 ; display line 2
.ELSE
sbrc rFlg,bPw ; check if pulse width displayed
rjmp CPw ; yes, calculate pulse width
rcall Calc ; calculate frequency
rjmp Loop1 ; and display frequency
CPw:
rcall CalcPw ; calculalate pulse width
.ENDIF
Loop1:
rcall LcdL1 ; display line 1
.IF dbghx
rcall LcdHexPar
.ENDIF
rjmp Loop ; go to sleep again
;
; **************************************************
; I N C L U D E T H E L C D R O U T I N E S
; **************************************************
;
.INCLUDE "Lcd8_02WO_rect.inc"
;
; Init-text of the LCD
;
LcdInitText:
.IF cLcdLn == 1
.IF cLcdLw == 40
.DB "Rectangle Generator DG4FAC ATmega8 V1.0 "
.ELSE
.IF cLcdLw == 24
.DB "Rect Generator M8 V1.0 "
.ELSE
.IF cLcdLw == 20
.DB "Rect Generator V1.0 "
.ELSE
.IF cLcdLw == 16
.DB "Rect-Gen M8 V1.0"
.ELSE
.DB "RG M8 V1"
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ELSE
.IF cLcdLw == 40
.DB "Rectangle Generator DG4FAC ATmega8 V1.0",0x0D
.DB "(C)2006 by info!at!avr-asm-tutorial.net "
.ELSE
.IF cLcdLw == 24
.DB "Rect Generator M8 V1.0 ",0x0D
.DB "www.avr-asm-tutorial.net"
.ELSE
.IF cLcdLw == 20
.DB "Rect Generator V1.0",0x0D
.DB "avr-asm-tutorial.net"
.ELSE
.IF cLcdLw == 16
.DB "Rect-Gen M8
V1.0",0x0D,"avr-asm-tutorial",0x00
.ELSE
.DB "RG M8 V1",0x0D,"avr-
asm"
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.ENDIF
.DB 0,0
;
; **************************************************
; C O N V E R S I O N - T A B L E
; **************************************************
;
.INCLUDE "rectgen_m8_table.inc"
;

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8_v1_main.html (2 of 2)1/20/2009 7:57:40 PM


Signal Generator ATmega8

Pfad: Home => AVR-Overview => Applications => Signal Generator

Signal Generator with an ATmega8


This application demonstrates a digital signal generator with an ATMEL
ATmega8 with the following properties:

● Adjustabe frequency range: 0,25 c/s to 8 Mcs/s in 1024 steps


● Wide dynamic range of the frequency without mechanic switching
● Reprogramming of the frequency characteristics possible
● Adjustable pulse-width from 0.00 to 100.00% in 1024 steps
● Independant adjustment of pulse-width and frequency
● Xtal base frequency 16 Mcs/s for stable frequency
● Normal and inverted output
● Polarity change by switch (active low, active high)
● Selectable display: frequency, time, rounds per minute and pulse-width
● Suitable for single- and two-line LCDs with 16 to 40 characters per line
● English or german notation selectable

0. Content
● 1. Hardware
❍ 1.1 Processor section

❍ 1.2 ISP-Interface

❍ 1.3 LCD-Display

❍ 1.4 External connections

■ 1.4.1 Adjusting frequency and pulse-width

■ 1.4.2 Switches

■ 1.4.3 Output connections

❍ 1.5 Power supply

❍ 1.6 Hints on mounting the device

● 2. Use
❍ 2.1 Switches

❍ 2.2 Output signals

● 3. How the device works


❍ 3.1 Processor section

❍ 3.2 LCD display

❍ 3.3 ISP interface

● 4. Software
❍ 4.1 Prior to assembling

❍ 4.2 Frequency table

❍ 4.3 Switches

❍ 4.4 Commented source code

1 Hardware
Th

hardware consists of the AVR processor, the In-System-Programming (ISP) connector, the LCD and diverse external
connections.

1.1 Processor part

The processor is attached to the following external components.


The operating voltage of 5 V is supplied via the pins 7 (+5 V) and 8 (0 V) and blocked by a ceramic capacitor.
Pin 1 (= RESET-pin) is tied to the positive operating voltage. On the Xtal pins 9 und 10 (XT1, XT2) an Xtal of 16 MHz is
connected. Disconnecting the internal RC clock source and activation of the Xtal clock generator is done by setting the
respective fuses. Both Xtal inputs are equipped with ceramic capacitors of 22 pF to improve switching characteristics.
The operating voltage for the AD converter is supplied over a LC network of a 22 µH coil and a capacitor of 100 nF on
pin 20 (AVCC). As reference voltage AVCC is selected by software, so a capacitor to ground is connected to the AREF
(pin 21).

1.2 ISP interface

The ISP interface allows programming of the AVR in the completed system without removing the chip.
ISP uses the port bits 5 (SCK), 4 (MISO), 3 (MOSI) and the RESET on pin 1. MISO is also used to drive a control signal of
the LCD. Pinning of the 10-pole ISP connector is compatible with the ATMEL-/KANDA- standard. The LED connected to
the ISP connector signals programming currently active.

1.3 LCD display

As display a standard LCD is used. It is connected via a 14 pole parallel cable and connectors that fit to the 14-pole
connection of the LCD.
The control port of the LCD is connected to the port bits PB0 (LCD Enable) and PB4 (LCD RS input). LCD Enable is by
default tied to ground over a resistor of 10 k to avoid spurious signals on that line during phases where the pin PB0 is not
(yet) initialised (during startup and during ISP programming).
LCD-R/W is tied to ground, because the display is not read.
The data port of the LCD is connected to the port D of the AVR. Data transfer to the LCD uses the 8 bits parallel, no
multiplexing takes place.

1.4 External connections

With the exception of the LCD ad the operating voltage supply, that use separate connections, all other external components
are connected via a single 14-pole connection. This has the advantage that the processor board can be easily disconnected and
testet separately. The 14-pole cable can be separated to portions reaching the different external components systematically.

1.4.1 Frequency and pulse-width adjust

The first four cables are connected to the operating voltage and the first two AD channel inputs of the AVR.
The AD channels ADC0 (Frequency adjust) and ADC1 (Pulse-width) are connected to the middle of the variable resistors.
The variable resistors are of the 10-turn-type and are connected to the operating voltage. Their nominal value and linearity
are uncritical, because the real values are displayed on the LCD.
Directly on the variable resistors the signal lines to the ADCs are blocked by capacitors to ground to avoid noise on the ADC
inputs.

1.4.2 Switches

The next five connections of the 14-pole cable are connected to the port inputs PC2 to PC5. The switch connected to PC5 is
only necessary if a single-line LCD is used. Leave this line open, if you use a two-line LCD.
All switches connect the port inputs with ground, if closed. The ports have software-activated pullup resistors and are so held
on the operating voltage, if not pulled to ground.

1.4.3 Output connections

The following three lines of the cable are connected to the outputs of the timer (normal and inverted). These have to be
soldered to the CINCH output connectors.
The output yield digital signals with the typical characteristics of the AVR output drivers and are directly coupled to the
output connectors. The outputs are short-circuit protected, but are not protected against voltages applied externally.

1.5 Power supply

The power supply provides a stabilised operating voltage of 5 V at a current of approximately 20 mA. The supply current is
depending from the variable resistors. Processor and LCD require below 10 mA, so the whole generator can also be supplied
by batteries.
To use a small transformer with 6 V secondary voltage, a rectifier bridge with Schottky diodes and a low-drop regulator is
used. With a transformer of 7,5 V secondary voltage or more these components can be exchanged to standard components.
The charger capacitor has a relatively high capacity, it can be reduced.
The two Tantal capacitors suppress instabilities of the regulator.

1.6 Hints on mounting the device

Putting
the
components
together
on a piece
of
experimental
board is
uncritical.
The 14-
pole
connection
to the
LCD is
located to
the left,
the 14-
pole
connection
to the
external
components
(variable
resistors,
switches,
output
connectors)
to the
right. For
easy mounting the parallel cable can be separated into portions of four, five, three and two lines. Please don't forget the two
capacitors on the middle of the variable resistors.
The 10-pole ISP interface is not used very often, so it is not accessible on the outside of the casing. The power supply is
located on the upper left of the plastic case.

2 Use
After switching power on the LCD displays a message for about 2.5 seconds, showing the machine's function, the software
version and the copyright, with the format depending from the available number of characters of the line. The machine the is
ready to operate.

2.1 Switches

The switch Time changes the display from frequency (switch open) to time (switch closed). Output of the frequency is in Hz
(cs/s) with two decimals, output of the time is in microseconds. Both values are rounded and formatted with thousands
separators.
If frequency output is selected, the switch Rpm changes from frequency to rounds per minute (= 60 * f). If the output of time
is selected, this switch is ignored.
The switch Inv inverts the output signals by software without changing the output connector.
If a single-line LCD is used, the switch Pulse causes the display to show the pulse-width in % instead of the frequency/time
normally displayed. In case of a two-line LCD the pulse-width is permanently displayed on line 2.

2.2 Output signals

The digital output signal is available in positive and inverted form on the two CINCH connectors. To avoid capacitive effects
the lines should be short and not shielded.

3 How is it working?
This section describes the functioning of the processor, of the ISP interface and the LCD display.

3.1 Processor portion

The processor ATmega8 works with an external Xtal and the respective internal oscillator. Because the processor is shipped
with an internal RC oscillator of 1 Mcs/s, the respective fuses must be set first to use the Xtal as clock source. The following
fuse combinations must be used:

● CKOPT = 0
● CLKSEL3..CKSEL0 = 1111
● SUT1..SUT0 = 11 or 10

Reprogramming of these fuses can either be performed externally on a programming board (e.g. with a STK500 and the
ATMEL Studio) or in the completed system with the ISP interface (e.g. with PonyProg2000).

By programming the fuses with an STK500 the


Xtal must be connected to the device, otherwise
the Mega8 will not respond any more after the
fuses are programmed. The fuses are correctly
programmed by selecting one of the two last
options of the device.

When using
PonyProg please note
that the fuses are
displayed inverted.
To have an
orientation: by default
CKSEL3..CKSEL0
are 0001 and SUT1..
SUT0 are 10. Read
the fuses by pushing
the Read-Button first.
Of course, the Xtal
should be mounted to
the AVR before
programming the
fuses. CLKSEL and
SUT1 fuses should be
programmed like displayed here, SUT0 can be programmed to either 1 or 0. If you encounter problems during startup, then
program this to 1 (SUT1:SUT0 = 11).

The open switch inputs are at the start pulled to high by software activation of the internal pull-up resistors. If the swichtes
are closed, the input lines are pulled to logic zero. The switch Pulse is only needed, if a single-line LCD is used.

Signal generation is performed with the internal 16-bit timer/counter TC1 in the Fast-PWM-mode. The graph shows the
function of TC1 in this mode and shows the parameters that affect the operation (blue).

The
clock

oscillator, controlled by an external Xtal, is divided by the TC1 prescaler either by 1, 8, 64, 256 or 1024 and drives the
counter. When the counter reaches the TOP value, which was written by software to the double register ICR1, the counter is
reset with the next clock cycle and the compare outputs OC1A (Portbit PB1, Pin 15) und OC1B (Portbit PB2, Pin 16) are
activated. The frequency of the generator so is defined by ICR1. Depending from the selected value for the pulse-width of the
signal, the compare values in the register pairs COMPA and COMPB are adjusted. If the counter reaches these compare
values, the respective compare output is deactivated and stays so until the counter reaches TOP.
The two outputs OC1A and OC1B are, by software, of different polarity. They produce inverted signals of the same duration.
The switch Inv inverts this polarity by software.

Frequency adjustment is done with the variable resistor attached to the ADC0 input. The resistor rings a voltage of between
0.000 and 5.000 V to the ADC0 (port PC0, pin 23). After conversion, a value between 0x00 and 0x1F results. This value is
used to pick a respective value for TOP in ICR1 from a table with 1024 values (Lookup-Table, Include file rectgen_m8_table.
inc). Depending from the value read from ADC0, the prescaler control byte for TC1 is also prepared. Both values are stored
in SRAM until the update of TC1 takes place.

Pulse-width adjustment is done with the second variable resistor and the voltage reaches ADC1 (port PC1, pin 24), which is
also converted to a value between 0x00 und 0x1F. The TOP value is multiplied by this conversion value and then divided by
1024 to yield the compare value, next to be written to COMPA and COMPB.
During the same cycle, the switch Inv is read and the resulting control value for the correct polarity of OC1A and OC1B is
determined.

With the parameters mentioned, the TC1 counter runs free without additional software overhead. In order to update these
parameters the 8-bit timer/counter TC0 is used. The TC0 prescaler divides the system clock by 1024 and overflows after 256
prescaler pulses (@16Mcs/s: every 16,384 ms). TC0 interrupts and decrements a register, from 30. If this reaches zero (after
492 ms), the AD converter is connected to channel 0 and the first conversion is started.
The ADC runs with a clock that is derived from the system clock and divided by 128. After the first ADC result is complete,
the ADC interrupts the CPU. The interrupt service routine reads the result to a double register, sets a flag bit, muxes channel
1 to the ADC and starts the second conversion. If the result of the second conversion interrupts the CPU, this result is read,
the ADC is switched off and a signal flag is set.
The conversion of the ADC values and the update of TC1 is done asynchroneous in the main program loop, after the signal
flag had been set by the interrupt service routine. The ADC values are converted and TC1 is programmed with the new
parameters. After programming the TC1, the LCD is updated and the main program loop ends until the next TC0 overflow
interrupt wakes up the CPU.

3.2 LCD display

The LCD is connected to the 8-bit data port and the two conrol lines E(nable) and R(egister)S(elect). The R(ead)/W(rite)-line
is permanently on Write, the whole timing control is done in correct timing loops.

After program start and after a wait time for the internal init of the LCD the LCD is set to the following modes:

● 8-Bit interface
● Single or two line operation (depending from the values in the software)
● no display shift
● cursor off
● blinking off

Then, for 2.5 seconds a message is displayed.

After each update of the TC1 timer the LCD is also updated. First the CTC value in ICR1 is multiplicated by the prescaler
value (1, 8, 64, 256, 1024). I displaying of the frequency is selected, the clock frequency, multiplied by 100, is divided by this
value to yield an integer representing the frequency with a resolution of 0.01 cs/s. If displaying of the time is selected (switch
Time closed), the CTC value in ICR1 is multiplied by the prescaler value, and then multiplied by the factor
25.600.000.000 / clock (@16MHz: 1.600) to yield the time in microseconds (*100). If a two-line LCD is used, the value of
frequency or time is displayed on line 1. In case of a single-line display, this is displayed only if the switch Pulse is open.

The pulse-width is calculated by multiplying the compare value in COMPA or COMPB by 10,000 and dividing by the CTC
value in ICR1. The resulting integer is the pulse-width in % with a resolution of 0.01%. This value is written on line 2 (on a
two-line LCD) or written on line 1 (of a single-line LCD, if switch Pulse is closed).
The display is updated approximately 2 times per second.

At higher frequencies the frequency and pulse-width cannot be adjusted to accurate values due to the limited resolution of the
16-bit counter. This is recognised by the last two decimals being displayed. Due to the fact that the displayed numbers are
calculated from the real values used in TC1, these numbers are correct.

3.3 ISP interface

The ISP interface is for updating the software in circuit. The data and clock signals MOSI, MISO and SCK are accessed on
the 1o-pole connector. Via the RESET line (port PC6, pin 1) the ISP interface brings the ATmega8 to the programming
mode. After releasing RESET, the AVR restarts.
The programming LED indicates an active programming cycle, is only active in case of programming. If not build in, or if a
6-pin connector is used instead of the 10-pin standard, this does not change functioning.

4 Software
Te software is written exclusively in assembler language and divided into three different packages. Prior to assembling the
source code a number of parameters has to be adjusted to optimise the hardware.

4.1 Prior to assembling

4.1.1 Frequency table

The frequency table in the file rectgen_m8_table.inc has 1024 words for converting the selected voltage to the CTC value for
ICR1. The values were calculated with a Spreadsheet and exported as an Include-Text-file. If you make changes in that table,
please note that this may have consequences for the prescaler values. In that case you will have to readjust the prescaler
values in the routine Convert in the file rectgen_m8_v1.asm (current values: 392, 225, 60 and 3).

If changing the clock frequency of the Xtal oscillator the constant clock will have to be changed. In that case also the 5-byte-
constants cDivFx and cDivUx have to be changed accordingly. These cannot be calculated by the assembler due to overflow
problems. Note that changes in the clock frequency are automatically changing the LCD timing loops, no additional adjusts
in the driver routine are necessary.

The constants cLcdLw and cLcdLn define the connected LCD. Inproper settings might cause strange effects on the display.

The constant cLcdMicro defines the micro character of the connected LCD. The default is not a micro but a u, because some
displays do not have greek characters and do not use 0xE4 for that character.

The constant cEn enables english thousands- and decimal-separators.

4.1.2 Diverse switches

The switches Time, Rpm, Inv and Pulse can be placed to different pins, this can be re-defined with the constants pbTime,
pbRpm, pbInv and pbPwm.
The switches dbgon and dbghx are for debugging only. For correct function of the software these must be set to zero!

4.2 Commented source code

The commented source code is available in HTML-format

● Source code of the main program


● LCD drive routines
● Frequency table

and in zipped form as assembler source code: Assembler source code.

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8.html1/20/2009 7:58:04 PM
Signal Generator ATmega8

Pfad: Home => AVR-Overview => Applications => Signal Generator => LCD routines

Signal generator with


ATmega8 - Source
code LCD routines

;
; *******************************************************
; * Include routines for the LCD display, provides the *
; * basic routines for initiation of an LCD display and *
; * for displaying text on it, written for single- and *
; * two-line LCDs, 8-bit-interface, HD44780-compatible *
; * display *
; * (C)2006 by g.schmidt, info!at!avr-asm-tutorial.net *
; *******************************************************
;
;
; Characteristics of the hardware:
;
.EQU pLcdDataOut = PORTD ; Data Port that the LCD is connected to
.EQU pLcdDataIn = PIND ; dto., the input port
.EQU pLcdDataDir = DDRD ; dto., direction port
.EQU pLcdEOut = PORTB ; Control Port for the LCD bit E
.EQU pLcdEDir = DDRB ; Control Port direction for the LCD bit E
.EQU pLcdRsOut = PORTB ; dto., for LCD-RS
.EQU pLcdRsDir = DDRB ; dto., direction port
.EQU bLcdEOut = 0 ; Portbit Control bit E of the LCD
.EQU bLcdRSOut = 4 ; Portbit Control bit RS of the LCD
;
; Further required for assembling:
;
; Type Name Explanations
; --------------------------------------------------------------
; Constant Clock Processor frequency in cs/s, range 1..16 Mcs/s
; cLcdLw Number of characters per line of the LCD
; cLcdLn Number of lines of the LCD (1 or 2)
; Register rmp Multi-purpose register (R16..R31)
; --------------------------------------------------------------
;
; Provided routines:
;
; Name Parameters Provided task
; ------------------------------------------------------
; LcdInit Z:Text1 in flash Inits the LCD and displays
; memory (null- the text1 that Z points to,
; terminated), waits for 1.5 seconds and
; lines separate
; by char
; X:Text2 in flash displays the text2 that X
; Uses: R25:R24 points to
; LcdFlash Z: Text in flash Displays the text in flash
; memory that Z points to
; LcdHome -- Sets display position to
; start of line 1
; LcdChar R0 = character Displays the character in
; R0 on the current position
; LcdLine1 Z:Text in SRAM Displays the text in SRAM
; on line 1 of the LCD
; LcdLine2 Z:Text in SRAM Displays the text in SRAM
; on line 2 of the LCD
; -----------------------------------------------------
;
; -----------------------------------------------
; L C D I N I T I A T I O N R O U T I N E
; -----------------------------------------------
;
LcdInit:
cbi pLcdEOut,bLcdEOut ; clear LCD enable bit
sbi pLcdEDir,bLcdEOut ; set E bit to be output
sbi pLcdRsDir,bLcdRSOut ; dto., RS bit
rcall Delay360ms ; wait for LCD's internal init
ldi rmp,0xFF ; set LCD data port to be output
out pLcdDataDir,rmp
rcall Delay15ms ; wait 15 ms for internal display init
ldi rmp,0x38 ; set 8-bit-interface, 2 line LCD
rcall LcdStrobeC ; put contrl word out without busy
rcall Delay40us ; wait 40 us
ldi rmp,0x38 ; set again 8-bit-interface
rcall LcdStrobeC ; put contrl word out without busy
rcall Delay40us ; wait 40 us
ldi rmp,0x38 ; set 8-bit-interface and two lines
rcall LcdStrobeC ; put control word out without busy
rcall Delay40us ; wait 40 us
ldi rmp,0x08 ; set display off
rcall LcdStrobeC ; put contrl word out without busy
rcall Delay40us ; wait 40 us
ldi rmp,0x01 ; Display clear
rcall LcdStrobeC ; put contrl word out without busy
rcall Delay1m64s ; wait 1.64 ms
ldi rmp,0x06 ; Increment on, shift off
rcall LcdStrobeC ; put control word out without busy
ldi rmp,0x0C ; activate display, no cursor, no blinking
rcall LcdStrobeC ; put control word out without busy
rcall LcdHome ; set cursor position to home
rcall LcdFlash ; display text from Z in flash
rjmp Delay2s5 ; delay for 2.5 seconds
;
; -----------------------------------------------
; L C D W R I T E S U B R O U T I N E S
; -----------------------------------------------
;
; Display text at flash position Z on the display
;
LcdFlash:
lpm ; read the next char from flash memory
tst R0 ; reached the end of the string?
breq LcdFlash2
.IF cLcdLn>1
ldi rmp,0x0D ; carriage return?
cp rmp,R0
brne LcdFlash1 ; display character
ldi rmp,0xC0 ; line 2 address
rcall LcdStrobeC ; strobe control word
rcall Delay40us
adiw ZL,1 ; next char
rjmp LcdFlash ; go on
LcdFlash1:
.ENDIF
out pLcdDataOut,R0 ; character to output port
sbi pLcdRsOut,bLcdRSOut ; set RS
rcall LcdStrobeE ; strobe E
cbi pLcdRsOut,bLcdRSOut ; clear RS
rcall Delay40us
adiw ZL,1
rjmp LcdFlash ; next character
LcdFlash2:
ret
;
; Set the LCD output position to the beginning of line 1
;
LcdHome:
ldi rmp,0x02 ; set control to home
rcall LcdStrobeC ; strobe control word
rjmp Delay1m64s
;
; outputs rmp to lcd control and strobes E
;
LcdStrobeC:
out pLcdDataOut,rmp ; write control word to data port
cbi pLcdRsOut,bLcdRSOut ; clear RS
;
; Strobes E for the correct time
;
LcdStrobeE:
sbi pLcdEOut,bLcdEOut ; set E to one
nop ; wait at least 1 clock
.IF Clock>2 ; more than 2 Mcs/s
nop ; two nop
.ENDIF
.IF Clock>4 ; more than 4 Mcs/s
nop ; three nop
.ENDIF
.IF Clock>6 ; more than 6 Mcs/s
nop ; four nop
.ENDIF
.IF Clock>8 ; more than 8 Mcs/s
nop ; five nop
.ENDIF
.IF Clock>10 ; more than 10 Mcs/s
nop ; six nop
.ENDIF
.IF Clock>12 ; more than 12 Mcs/s
nop ; seven nop
.ENDIF
.IF Clock>14 ; more than 14 Mcs/s
nop ; eight nop
.ENDIF
cbi pLcdEOut,bLcdEOut ; clear E to zero
rjmp Delay40us
;
; Display the character in R0
;
LcdChar:
out pLcdDataOut,R0 ; output the character in R0
sbi pLcdRsOut,bLcdRSOut ; set RS
rjmp LcdStrobeE ; strobe E
;
; Displays the text at Z in SRAM on line 1 of the LCD
;
LcdLine1:
ldi rmp,0x80 ; set cursor to line 1
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine1a:
ld R0,Z+ ; read next char
rcall LcdChar
dec rmp
brne LcdLine1a
ret
;
; Displays the text at Z in SRAM on line 2 of the LCD
;
LcdLine2:
ldi rmp,0xC0 ; set cursor to line 2
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine2a:
ld R0,Z+ ; read next char
rcall LcdChar
dec rmp
brne LcdLine2a
ret
;
; -----------------------------------------------
; D E L A Y R O U T I N E S F O R L C D
; -----------------------------------------------
;
.SET clockus = clock/1000000
.IF clockus == 0 ; clock smaller than 1 Mcs/s
.SET clockus = 1
.ENDIF
;
; Delay for 2.5 seconds
;
Delay2s5:
push rmp
ldi rmp,2500/15+1 ; number of 15ms-delays
Delay2s5a:
rcall Delay15ms
dec rmp
brne Delay2s5a
pop rmp
ret
;
; Delay for 360 milliseconds
;
Delay360ms:
push rmp
ldi rmp,360/15+1 ; number of 15ms delays
Delay360ms1:
rcall Delay15ms
dec rmp
brne Delay360ms1
pop rmp
ret
;
; Delay for 15 milliseconds
;
Delay15ms:
push ZH ; save Z
push ZL
ldi ZH,HIGH((15000*clockus-16)/4)
ldi ZL,LOW((15000*clockus-16)/4)
Delay15ms1:
sbiw ZL,1
brne Delay15ms1
pop ZL
pop ZH
ret
;
; Delay for 1.64 milliseconds
;
Delay1m64s:
push ZH ; save Z
push ZL
ldi ZH,HIGH((1640*clockus-16)/4)
ldi ZL,LOW((1640*clockus-16)/4)
Delay1m64s1:
sbiw ZL,1
brne Delay1m64s1
pop ZL
pop ZH
ret
;
; Delay 40 microseconds
;
Delay40us:
push rmp
ldi rmp,(40*clockus-11)/3
Delay40us1:
dec rmp
brne Delay40us1
pop rmp
ret
;
; End of the LCD-Routines
;

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8_v1_lcd.html1/20/2009 7:58:11 PM
Signal Generator ATmega8

Pfad: Home => AVR-Overview => Applications => Signal Generator => Frequency table

Signal generator with


ATmega8 - Source
code frequency table

; Table for converting ADC-values to TC1 compare values


; TC1 prescaler: n<3: 1024, n<60: 256, n<225: 64, n<392: 8, above: 1
DataTable: ; 16MHz-counter TC1
.DW 0 ; nAdc= 0, f= off
.DW 62500 ; nAdc= 1, f= 0,25, upm= 15
.DW 31250 ; nAdc= 2, f= 0,5, upm= 30
.DW 62500 ; nAdc= 3, f= 1, upm= 60
.DW 59524 ; nAdc= 4, f= 1,05, upm= 63
.DW 56818 ; nAdc= 5, f= 1,1, upm= 66
.DW 54348 ; nAdc= 6, f= 1,15, upm= 69
.DW 52083 ; nAdc= 7, f= 1,2, upm= 72
.DW 50000 ; nAdc= 8, f= 1,25, upm= 75
.DW 48077 ; nAdc= 9, f= 1,3, upm= 78
.DW 46296 ; nAdc= 10, f= 1,35, upm= 81
.DW 44643 ; nAdc= 11, f= 1,4, upm= 84
.DW 43103 ; nAdc= 12, f= 1,45, upm= 87
.DW 41667 ; nAdc= 13, f= 1,5, upm= 90
.DW 40323 ; nAdc= 14, f= 1,55, upm= 93
.DW 39063 ; nAdc= 15, f= 1,6, upm= 96
.DW 37879 ; nAdc= 16, f= 1,65, upm= 99
.DW 36765 ; nAdc= 17, f= 1,7, upm= 102
.DW 35714 ; nAdc= 18, f= 1,75, upm= 105
.DW 34722 ; nAdc= 19, f= 1,8, upm= 108
.DW 33784 ; nAdc= 20, f= 1,85, upm= 111
.DW 32895 ; nAdc= 21, f= 1,9, upm= 114
.DW 32051 ; nAdc= 22, f= 1,95, upm= 117
.DW 31250 ; nAdc= 23, f= 2, upm= 120
.DW 30488 ; nAdc= 24, f= 2,05, upm= 123
.DW 29762 ; nAdc= 25, f= 2,1, upm= 126
.DW 29070 ; nAdc= 26, f= 2,15, upm= 129
.DW 28409 ; nAdc= 27, f= 2,2, upm= 132
.DW 27778 ; nAdc= 28, f= 2,25, upm= 135
.DW 27174 ; nAdc= 29, f= 2,3, upm= 138
.DW 26596 ; nAdc= 30, f= 2,35, upm= 141
.DW 26042 ; nAdc= 31, f= 2,4, upm= 144
.DW 25510 ; nAdc= 32, f= 2,45, upm= 147
.DW 25000 ; nAdc= 33, f= 2,5, upm= 150
.DW 24510 ; nAdc= 34, f= 2,55, upm= 153
.DW 24038 ; nAdc= 35, f= 2,6, upm= 156
.DW 23585 ; nAdc= 36, f= 2,65, upm= 159
.DW 23148 ; nAdc= 37, f= 2,7, upm= 162
.DW 22727 ; nAdc= 38, f= 2,75, upm= 165
.DW 22321 ; nAdc= 39, f= 2,8, upm= 168
.DW 21930 ; nAdc= 40, f= 2,85, upm= 171
.DW 21552 ; nAdc= 41, f= 2,9, upm= 174
.DW 21186 ; nAdc= 42, f= 2,95, upm= 177
.DW 20833 ; nAdc= 43, f= 3, upm= 180
.DW 20492 ; nAdc= 44, f= 3,05, upm= 183
.DW 20161 ; nAdc= 45, f= 3,1, upm= 186
.DW 19841 ; nAdc= 46, f= 3,15, upm= 189
.DW 19531 ; nAdc= 47, f= 3,2, upm= 192
.DW 19231 ; nAdc= 48, f= 3,25, upm= 195
.DW 18939 ; nAdc= 49, f= 3,3, upm= 198
.DW 18657 ; nAdc= 50, f= 3,35, upm= 201
.DW 18382 ; nAdc= 51, f= 3,4, upm= 204
.DW 18116 ; nAdc= 52, f= 3,45, upm= 207
.DW 17857 ; nAdc= 53, f= 3,5, upm= 210
.DW 17606 ; nAdc= 54, f= 3,55, upm= 213
.DW 17361 ; nAdc= 55, f= 3,6, upm= 216
.DW 17123 ; nAdc= 56, f= 3,65, upm= 219
.DW 16892 ; nAdc= 57, f= 3,7, upm= 222
.DW 16667 ; nAdc= 58, f= 3,75, upm= 225
.DW 16447 ; nAdc= 59, f= 3,8, upm= 228
.DW 64935 ; nAdc= 60, f= 3,85, upm= 231
.DW 64103 ; nAdc= 61, f= 3,9, upm= 234
.DW 63291 ; nAdc= 62, f= 3,95, upm= 237
.DW 62500 ; nAdc= 63, f= 4, upm= 240
.DW 61728 ; nAdc= 64, f= 4,05, upm= 243
.DW 60976 ; nAdc= 65, f= 4,1, upm= 246
.DW 60241 ; nAdc= 66, f= 4,15, upm= 249
.DW 59524 ; nAdc= 67, f= 4,2, upm= 252
.DW 58824 ; nAdc= 68, f= 4,25, upm= 255
.DW 58140 ; nAdc= 69, f= 4,3, upm= 258
.DW 57471 ; nAdc= 70, f= 4,35, upm= 261
.DW 56818 ; nAdc= 71, f= 4,4, upm= 264
.DW 56180 ; nAdc= 72, f= 4,45, upm= 267
.DW 55556 ; nAdc= 73, f= 4,5, upm= 270
.DW 54945 ; nAdc= 74, f= 4,55, upm= 273
.DW 54348 ; nAdc= 75, f= 4,6, upm= 276
.DW 53763 ; nAdc= 76, f= 4,65, upm= 279
.DW 53191 ; nAdc= 77, f= 4,7, upm= 282
.DW 52632 ; nAdc= 78, f= 4,75, upm= 285
.DW 52083 ; nAdc= 79, f= 4,8, upm= 288
.DW 51546 ; nAdc= 80, f= 4,85, upm= 291
.DW 51020 ; nAdc= 81, f= 4,9, upm= 294
.DW 50505 ; nAdc= 82, f= 4,95, upm= 297
.DW 50000 ; nAdc= 83, f= 5, upm= 300
.DW 49505 ; nAdc= 84, f= 5,05, upm= 303
.DW 49020 ; nAdc= 85, f= 5,1, upm= 306
.DW 48544 ; nAdc= 86, f= 5,15, upm= 309
.DW 48077 ; nAdc= 87, f= 5,2, upm= 312
.DW 47619 ; nAdc= 88, f= 5,25, upm= 315
.DW 47170 ; nAdc= 89, f= 5,3, upm= 318
.DW 46729 ; nAdc= 90, f= 5,35, upm= 321
.DW 46296 ; nAdc= 91, f= 5,4, upm= 324
.DW 45872 ; nAdc= 92, f= 5,45, upm= 327
.DW 45455 ; nAdc= 93, f= 5,5, upm= 330
.DW 45045 ; nAdc= 94, f= 5,55, upm= 333
.DW 44643 ; nAdc= 95, f= 5,6, upm= 336
.DW 44248 ; nAdc= 96, f= 5,65, upm= 339
.DW 43860 ; nAdc= 97, f= 5,7, upm= 342
.DW 43478 ; nAdc= 98, f= 5,75, upm= 345
.DW 43103 ; nAdc= 99, f= 5,8, upm= 348
.DW 42735 ; nAdc= 100, f= 5,85, upm= 351
.DW 42373 ; nAdc= 101, f= 5,9, upm= 354
.DW 42017 ; nAdc= 102, f= 5,95, upm= 357
.DW 41667 ; nAdc= 103, f= 6, upm= 360
.DW 41322 ; nAdc= 104, f= 6,05, upm= 363
.DW 40984 ; nAdc= 105, f= 6,1, upm= 366
.DW 40650 ; nAdc= 106, f= 6,15, upm= 369
.DW 40323 ; nAdc= 107, f= 6,2, upm= 372
.DW 40000 ; nAdc= 108, f= 6,25, upm= 375
.DW 39683 ; nAdc= 109, f= 6,3, upm= 378
.DW 39370 ; nAdc= 110, f= 6,35, upm= 381
.DW 39063 ; nAdc= 111, f= 6,4, upm= 384
.DW 38760 ; nAdc= 112, f= 6,45, upm= 387
.DW 38462 ; nAdc= 113, f= 6,5, upm= 390
.DW 38168 ; nAdc= 114, f= 6,55, upm= 393
.DW 37879 ; nAdc= 115, f= 6,6, upm= 396
.DW 37594 ; nAdc= 116, f= 6,65, upm= 399
.DW 37313 ; nAdc= 117, f= 6,7, upm= 402
.DW 37037 ; nAdc= 118, f= 6,75, upm= 405
.DW 36765 ; nAdc= 119, f= 6,8, upm= 408
.DW 36496 ; nAdc= 120, f= 6,85, upm= 411
.DW 36232 ; nAdc= 121, f= 6,9, upm= 414
.DW 35971 ; nAdc= 122, f= 6,95, upm= 417
.DW 35714 ; nAdc= 123, f= 7, upm= 420
.DW 35461 ; nAdc= 124, f= 7,05, upm= 423
.DW 35211 ; nAdc= 125, f= 7,1, upm= 426
.DW 34965 ; nAdc= 126, f= 7,15, upm= 429
.DW 34722 ; nAdc= 127, f= 7,2, upm= 432
.DW 34483 ; nAdc= 128, f= 7,25, upm= 435
.DW 34247 ; nAdc= 129, f= 7,3, upm= 438
.DW 34014 ; nAdc= 130, f= 7,35, upm= 441
.DW 33784 ; nAdc= 131, f= 7,4, upm= 444
.DW 33557 ; nAdc= 132, f= 7,45, upm= 447
.DW 33333 ; nAdc= 133, f= 7,5, upm= 450
.DW 33113 ; nAdc= 134, f= 7,55, upm= 453
.DW 32895 ; nAdc= 135, f= 7,6, upm= 456
.DW 32680 ; nAdc= 136, f= 7,65, upm= 459
.DW 32468 ; nAdc= 137, f= 7,7, upm= 462
.DW 32258 ; nAdc= 138, f= 7,75, upm= 465
.DW 32051 ; nAdc= 139, f= 7,8, upm= 468
.DW 31847 ; nAdc= 140, f= 7,85, upm= 471
.DW 31646 ; nAdc= 141, f= 7,9, upm= 474
.DW 31447 ; nAdc= 142, f= 7,95, upm= 477
.DW 31250 ; nAdc= 143, f= 8, upm= 480
.DW 31056 ; nAdc= 144, f= 8,05, upm= 483
.DW 30864 ; nAdc= 145, f= 8,1, upm= 486
.DW 30675 ; nAdc= 146, f= 8,15, upm= 489
.DW 30488 ; nAdc= 147, f= 8,2, upm= 492
.DW 30303 ; nAdc= 148, f= 8,25, upm= 495
.DW 30120 ; nAdc= 149, f= 8,3, upm= 498
.DW 29940 ; nAdc= 150, f= 8,35, upm= 501
.DW 29762 ; nAdc= 151, f= 8,4, upm= 504
.DW 29586 ; nAdc= 152, f= 8,45, upm= 507
.DW 29412 ; nAdc= 153, f= 8,5, upm= 510
.DW 29240 ; nAdc= 154, f= 8,55, upm= 513
.DW 29070 ; nAdc= 155, f= 8,6, upm= 516
.DW 28902 ; nAdc= 156, f= 8,65, upm= 519
.DW 28736 ; nAdc= 157, f= 8,7, upm= 522
.DW 28571 ; nAdc= 158, f= 8,75, upm= 525
.DW 28409 ; nAdc= 159, f= 8,8, upm= 528
.DW 28249 ; nAdc= 160, f= 8,85, upm= 531
.DW 28090 ; nAdc= 161, f= 8,9, upm= 534
.DW 27933 ; nAdc= 162, f= 8,95, upm= 537
.DW 27778 ; nAdc= 163, f= 9, upm= 540
.DW 27624 ; nAdc= 164, f= 9,05, upm= 543
.DW 27473 ; nAdc= 165, f= 9,1, upm= 546
.DW 27322 ; nAdc= 166, f= 9,15, upm= 549
.DW 27174 ; nAdc= 167, f= 9,2, upm= 552
.DW 27027 ; nAdc= 168, f= 9,25, upm= 555
.DW 26882 ; nAdc= 169, f= 9,3, upm= 558
.DW 26738 ; nAdc= 170, f= 9,35, upm= 561
.DW 26596 ; nAdc= 171, f= 9,4, upm= 564
.DW 26455 ; nAdc= 172, f= 9,45, upm= 567
.DW 26316 ; nAdc= 173, f= 9,5, upm= 570
.DW 26178 ; nAdc= 174, f= 9,55, upm= 573
.DW 26042 ; nAdc= 175, f= 9,6, upm= 576
.DW 25907 ; nAdc= 176, f= 9,65, upm= 579
.DW 25773 ; nAdc= 177, f= 9,7, upm= 582
.DW 25641 ; nAdc= 178, f= 9,75, upm= 585
.DW 25510 ; nAdc= 179, f= 9,8, upm= 588
.DW 25381 ; nAdc= 180, f= 9,85, upm= 591
.DW 25253 ; nAdc= 181, f= 9,9, upm= 594
.DW 25126 ; nAdc= 182, f= 9,95, upm= 597
.DW 25000 ; nAdc= 183, f= 10, upm= 600
.DW 23810 ; nAdc= 184, f= 10,5, upm= 630
.DW 22727 ; nAdc= 185, f= 11, upm= 660
.DW 21739 ; nAdc= 186, f= 11,5, upm= 690
.DW 20833 ; nAdc= 187, f= 12, upm= 720
.DW 20000 ; nAdc= 188, f= 12,5, upm= 750
.DW 19231 ; nAdc= 189, f= 13, upm= 780
.DW 18519 ; nAdc= 190, f= 13,5, upm= 810
.DW 17857 ; nAdc= 191, f= 14, upm= 840
.DW 17241 ; nAdc= 192, f= 14,5, upm= 870
.DW 16667 ; nAdc= 193, f= 15, upm= 900
.DW 16129 ; nAdc= 194, f= 15,5, upm= 930
.DW 15625 ; nAdc= 195, f= 16, upm= 960
.DW 15152 ; nAdc= 196, f= 16,5, upm= 990
.DW 14706 ; nAdc= 197, f= 17, upm= 1020
.DW 14286 ; nAdc= 198, f= 17,5, upm= 1050
.DW 13889 ; nAdc= 199, f= 18, upm= 1080
.DW 13514 ; nAdc= 200, f= 18,5, upm= 1110
.DW 13158 ; nAdc= 201, f= 19, upm= 1140
.DW 12821 ; nAdc= 202, f= 19,5, upm= 1170
.DW 12500 ; nAdc= 203, f= 20, upm= 1200
.DW 12195 ; nAdc= 204, f= 20,5, upm= 1230
.DW 11905 ; nAdc= 205, f= 21, upm= 1260
.DW 11628 ; nAdc= 206, f= 21,5, upm= 1290
.DW 11364 ; nAdc= 207, f= 22, upm= 1320
.DW 11111 ; nAdc= 208, f= 22,5, upm= 1350
.DW 10870 ; nAdc= 209, f= 23, upm= 1380
.DW 10638 ; nAdc= 210, f= 23,5, upm= 1410
.DW 10417 ; nAdc= 211, f= 24, upm= 1440
.DW 10204 ; nAdc= 212, f= 24,5, upm= 1470
.DW 10000 ; nAdc= 213, f= 25, upm= 1500
.DW 9804 ; nAdc= 214, f= 25,5, upm= 1530
.DW 9615 ; nAdc= 215, f= 26, upm= 1560
.DW 9434 ; nAdc= 216, f= 26,5, upm= 1590
.DW 9259 ; nAdc= 217, f= 27, upm= 1620
.DW 9091 ; nAdc= 218, f= 27,5, upm= 1650
.DW 8929 ; nAdc= 219, f= 28, upm= 1680
.DW 8772 ; nAdc= 220, f= 28,5, upm= 1710
.DW 8621 ; nAdc= 221, f= 29, upm= 1740
.DW 8475 ; nAdc= 222, f= 29,5, upm= 1770
.DW 8333 ; nAdc= 223, f= 30, upm= 1800
.DW 8197 ; nAdc= 224, f= 30,5, upm= 1830
.DW 64516 ; nAdc= 225, f= 31, upm= 1860
.DW 63492 ; nAdc= 226, f= 31,5, upm= 1890
.DW 62500 ; nAdc= 227, f= 32, upm= 1920
.DW 61538 ; nAdc= 228, f= 32,5, upm= 1950
.DW 60606 ; nAdc= 229, f= 33, upm= 1980
.DW 59701 ; nAdc= 230, f= 33,5, upm= 2010
.DW 58824 ; nAdc= 231, f= 34, upm= 2040
.DW 57971 ; nAdc= 232, f= 34,5, upm= 2070
.DW 57143 ; nAdc= 233, f= 35, upm= 2100
.DW 56338 ; nAdc= 234, f= 35,5, upm= 2130
.DW 55556 ; nAdc= 235, f= 36, upm= 2160
.DW 54795 ; nAdc= 236, f= 36,5, upm= 2190
.DW 54054 ; nAdc= 237, f= 37, upm= 2220
.DW 53333 ; nAdc= 238, f= 37,5, upm= 2250
.DW 52632 ; nAdc= 239, f= 38, upm= 2280
.DW 51948 ; nAdc= 240, f= 38,5, upm= 2310
.DW 51282 ; nAdc= 241, f= 39, upm= 2340
.DW 50633 ; nAdc= 242, f= 39,5, upm= 2370
.DW 50000 ; nAdc= 243, f= 40, upm= 2400
.DW 49383 ; nAdc= 244, f= 40,5, upm= 2430
.DW 48780 ; nAdc= 245, f= 41, upm= 2460
.DW 48193 ; nAdc= 246, f= 41,5, upm= 2490
.DW 47619 ; nAdc= 247, f= 42, upm= 2520
.DW 47059 ; nAdc= 248, f= 42,5, upm= 2550
.DW 46512 ; nAdc= 249, f= 43, upm= 2580
.DW 45977 ; nAdc= 250, f= 43,5, upm= 2610
.DW 45455 ; nAdc= 251, f= 44, upm= 2640
.DW 44944 ; nAdc= 252, f= 44,5, upm= 2670
.DW 44444 ; nAdc= 253, f= 45, upm= 2700
.DW 43956 ; nAdc= 254, f= 45,5, upm= 2730
.DW 43478 ; nAdc= 255, f= 46, upm= 2760
.DW 43011 ; nAdc= 256, f= 46,5, upm= 2790
.DW 42553 ; nAdc= 257, f= 47, upm= 2820
.DW 42105 ; nAdc= 258, f= 47,5, upm= 2850
.DW 41667 ; nAdc= 259, f= 48, upm= 2880
.DW 41237 ; nAdc= 260, f= 48,5, upm= 2910
.DW 40816 ; nAdc= 261, f= 49, upm= 2940
.DW 40404 ; nAdc= 262, f= 49,5, upm= 2970
.DW 40000 ; nAdc= 263, f= 50, upm= 3000
.DW 39604 ; nAdc= 264, f= 50,5, upm= 3030
.DW 39216 ; nAdc= 265, f= 51, upm= 3060
.DW 38835 ; nAdc= 266, f= 51,5, upm= 3090
.DW 38462 ; nAdc= 267, f= 52, upm= 3120
.DW 38095 ; nAdc= 268, f= 52,5, upm= 3150
.DW 37736 ; nAdc= 269, f= 53, upm= 3180
.DW 37383 ; nAdc= 270, f= 53,5, upm= 3210
.DW 37037 ; nAdc= 271, f= 54, upm= 3240
.DW 36697 ; nAdc= 272, f= 54,5, upm= 3270
.DW 36364 ; nAdc= 273, f= 55, upm= 3300
.DW 36036 ; nAdc= 274, f= 55,5, upm= 3330
.DW 35714 ; nAdc= 275, f= 56, upm= 3360
.DW 35398 ; nAdc= 276, f= 56,5, upm= 3390
.DW 35088 ; nAdc= 277, f= 57, upm= 3420
.DW 34783 ; nAdc= 278, f= 57,5, upm= 3450
.DW 34483 ; nAdc= 279, f= 58, upm= 3480
.DW 34188 ; nAdc= 280, f= 58,5, upm= 3510
.DW 33898 ; nAdc= 281, f= 59, upm= 3540
.DW 33613 ; nAdc= 282, f= 59,5, upm= 3570
.DW 33333 ; nAdc= 283, f= 60, upm= 3600
.DW 33058 ; nAdc= 284, f= 60,5, upm= 3630
.DW 32787 ; nAdc= 285, f= 61, upm= 3660
.DW 32520 ; nAdc= 286, f= 61,5, upm= 3690
.DW 32258 ; nAdc= 287, f= 62, upm= 3720
.DW 32000 ; nAdc= 288, f= 62,5, upm= 3750
.DW 31746 ; nAdc= 289, f= 63, upm= 3780
.DW 31496 ; nAdc= 290, f= 63,5, upm= 3810
.DW 31250 ; nAdc= 291, f= 64, upm= 3840
.DW 31008 ; nAdc= 292, f= 64,5, upm= 3870
.DW 30769 ; nAdc= 293, f= 65, upm= 3900
.DW 30534 ; nAdc= 294, f= 65,5, upm= 3930
.DW 30303 ; nAdc= 295, f= 66, upm= 3960
.DW 30075 ; nAdc= 296, f= 66,5, upm= 3990
.DW 29851 ; nAdc= 297, f= 67, upm= 4020
.DW 29630 ; nAdc= 298, f= 67,5, upm= 4050
.DW 29412 ; nAdc= 299, f= 68, upm= 4080
.DW 29197 ; nAdc= 300, f= 68,5, upm= 4110
.DW 28986 ; nAdc= 301, f= 69, upm= 4140
.DW 28777 ; nAdc= 302, f= 69,5, upm= 4170
.DW 28571 ; nAdc= 303, f= 70, upm= 4200
.DW 28369 ; nAdc= 304, f= 70,5, upm= 4230
.DW 28169 ; nAdc= 305, f= 71, upm= 4260
.DW 27972 ; nAdc= 306, f= 71,5, upm= 4290
.DW 27778 ; nAdc= 307, f= 72, upm= 4320
.DW 27586 ; nAdc= 308, f= 72,5, upm= 4350
.DW 27397 ; nAdc= 309, f= 73, upm= 4380
.DW 27211 ; nAdc= 310, f= 73,5, upm= 4410
.DW 27027 ; nAdc= 311, f= 74, upm= 4440
.DW 26846 ; nAdc= 312, f= 74,5, upm= 4470
.DW 26667 ; nAdc= 313, f= 75, upm= 4500
.DW 26490 ; nAdc= 314, f= 75,5, upm= 4530
.DW 26316 ; nAdc= 315, f= 76, upm= 4560
.DW 26144 ; nAdc= 316, f= 76,5, upm= 4590
.DW 25974 ; nAdc= 317, f= 77, upm= 4620
.DW 25806 ; nAdc= 318, f= 77,5, upm= 4650
.DW 25641 ; nAdc= 319, f= 78, upm= 4680
.DW 25478 ; nAdc= 320, f= 78,5, upm= 4710
.DW 25316 ; nAdc= 321, f= 79, upm= 4740
.DW 25157 ; nAdc= 322, f= 79,5, upm= 4770
.DW 25000 ; nAdc= 323, f= 80, upm= 4800
.DW 24845 ; nAdc= 324, f= 80,5, upm= 4830
.DW 24691 ; nAdc= 325, f= 81, upm= 4860
.DW 24540 ; nAdc= 326, f= 81,5, upm= 4890
.DW 24390 ; nAdc= 327, f= 82, upm= 4920
.DW 24242 ; nAdc= 328, f= 82,5, upm= 4950
.DW 24096 ; nAdc= 329, f= 83, upm= 4980
.DW 23952 ; nAdc= 330, f= 83,5, upm= 5010
.DW 23810 ; nAdc= 331, f= 84, upm= 5040
.DW 23669 ; nAdc= 332, f= 84,5, upm= 5070
.DW 23529 ; nAdc= 333, f= 85, upm= 5100
.DW 23392 ; nAdc= 334, f= 85,5, upm= 5130
.DW 23256 ; nAdc= 335, f= 86, upm= 5160
.DW 23121 ; nAdc= 336, f= 86,5, upm= 5190
.DW 22989 ; nAdc= 337, f= 87, upm= 5220
.DW 22857 ; nAdc= 338, f= 87,5, upm= 5250
.DW 22727 ; nAdc= 339, f= 88, upm= 5280
.DW 22599 ; nAdc= 340, f= 88,5, upm= 5310
.DW 22472 ; nAdc= 341, f= 89, upm= 5340
.DW 22346 ; nAdc= 342, f= 89,5, upm= 5370
.DW 22222 ; nAdc= 343, f= 90, upm= 5400
.DW 22099 ; nAdc= 344, f= 90,5, upm= 5430
.DW 21978 ; nAdc= 345, f= 91, upm= 5460
.DW 21858 ; nAdc= 346, f= 91,5, upm= 5490
.DW 21739 ; nAdc= 347, f= 92, upm= 5520
.DW 21622 ; nAdc= 348, f= 92,5, upm= 5550
.DW 21505 ; nAdc= 349, f= 93, upm= 5580
.DW 21390 ; nAdc= 350, f= 93,5, upm= 5610
.DW 21277 ; nAdc= 351, f= 94, upm= 5640
.DW 21164 ; nAdc= 352, f= 94,5, upm= 5670
.DW 21053 ; nAdc= 353, f= 95, upm= 5700
.DW 20942 ; nAdc= 354, f= 95,5, upm= 5730
.DW 20833 ; nAdc= 355, f= 96, upm= 5760
.DW 20725 ; nAdc= 356, f= 96,5, upm= 5790
.DW 20619 ; nAdc= 357, f= 97, upm= 5820
.DW 20513 ; nAdc= 358, f= 97,5, upm= 5850
.DW 20408 ; nAdc= 359, f= 98, upm= 5880
.DW 20305 ; nAdc= 360, f= 98,5, upm= 5910
.DW 20202 ; nAdc= 361, f= 99, upm= 5940
.DW 20101 ; nAdc= 362, f= 99,5, upm= 5970
.DW 20000 ; nAdc= 363, f= 100, upm= 6000
.DW 19048 ; nAdc= 364, f= 105, upm= 6300
.DW 18182 ; nAdc= 365, f= 110, upm= 6600
.DW 17391 ; nAdc= 366, f= 115, upm= 6900
.DW 16667 ; nAdc= 367, f= 120, upm= 7200
.DW 16000 ; nAdc= 368, f= 125, upm= 7500
.DW 15385 ; nAdc= 369, f= 130, upm= 7800
.DW 14815 ; nAdc= 370, f= 135, upm= 8100
.DW 14286 ; nAdc= 371, f= 140, upm= 8400
.DW 13793 ; nAdc= 372, f= 145, upm= 8700
.DW 13333 ; nAdc= 373, f= 150, upm= 9000
.DW 12903 ; nAdc= 374, f= 155, upm= 9300
.DW 12500 ; nAdc= 375, f= 160, upm= 9600
.DW 12121 ; nAdc= 376, f= 165, upm= 9900
.DW 11765 ; nAdc= 377, f= 170, upm= 10200
.DW 11429 ; nAdc= 378, f= 174,99, upm= 10500
.DW 11111 ; nAdc= 379, f= 180, upm= 10800
.DW 10811 ; nAdc= 380, f= 185, upm= 11100
.DW 10526 ; nAdc= 381, f= 190,01, upm= 11400
.DW 10256 ; nAdc= 382, f= 195,01, upm= 11700
.DW 10000 ; nAdc= 383, f= 200, upm= 12000
.DW 9756 ; nAdc= 384, f= 205, upm= 12300
.DW 9524 ; nAdc= 385, f= 210, upm= 12600
.DW 9302 ; nAdc= 386, f= 215,01, upm= 12900
.DW 9091 ; nAdc= 387, f= 220, upm= 13200
.DW 8889 ; nAdc= 388, f= 225, upm= 13500
.DW 8696 ; nAdc= 389, f= 229,99, upm= 13799
.DW 8511 ; nAdc= 390, f= 234,99, upm= 14099
.DW 8333 ; nAdc= 391, f= 240,01, upm= 14401
.DW 65306 ; nAdc= 392, f= 245, upm= 14700
.DW 64000 ; nAdc= 393, f= 250, upm= 15000
.DW 62745 ; nAdc= 394, f= 255, upm= 15300
.DW 61538 ; nAdc= 395, f= 260, upm= 15600
.DW 60377 ; nAdc= 396, f= 265, upm= 15900
.DW 59259 ; nAdc= 397, f= 270, upm= 16200
.DW 58182 ; nAdc= 398, f= 275, upm= 16500
.DW 57143 ; nAdc= 399, f= 280, upm= 16800
.DW 56140 ; nAdc= 400, f= 285, upm= 17100
.DW 55172 ; nAdc= 401, f= 290, upm= 17400
.DW 54237 ; nAdc= 402, f= 295, upm= 17700
.DW 53333 ; nAdc= 403, f= 300, upm= 18000
.DW 52459 ; nAdc= 404, f= 305, upm= 18300
.DW 51613 ; nAdc= 405, f= 310, upm= 18600
.DW 50794 ; nAdc= 406, f= 315, upm= 18900
.DW 50000 ; nAdc= 407, f= 320, upm= 19200
.DW 49231 ; nAdc= 408, f= 325, upm= 19500
.DW 48485 ; nAdc= 409, f= 330, upm= 19800
.DW 47761 ; nAdc= 410, f= 335, upm= 20100
.DW 47059 ; nAdc= 411, f= 340, upm= 20400
.DW 46377 ; nAdc= 412, f= 345, upm= 20700
.DW 45714 ; nAdc= 413, f= 350, upm= 21000
.DW 45070 ; nAdc= 414, f= 355, upm= 21300
.DW 44444 ; nAdc= 415, f= 360, upm= 21600
.DW 43836 ; nAdc= 416, f= 365, upm= 21900
.DW 43243 ; nAdc= 417, f= 370, upm= 22200
.DW 42667 ; nAdc= 418, f= 375, upm= 22500
.DW 42105 ; nAdc= 419, f= 380, upm= 22800
.DW 41558 ; nAdc= 420, f= 385, upm= 23100
.DW 41026 ; nAdc= 421, f= 390, upm= 23400
.DW 40506 ; nAdc= 422, f= 395, upm= 23700
.DW 40000 ; nAdc= 423, f= 400, upm= 24000
.DW 39506 ; nAdc= 424, f= 405, upm= 24300
.DW 39024 ; nAdc= 425, f= 410, upm= 24600
.DW 38554 ; nAdc= 426, f= 415, upm= 24900
.DW 38095 ; nAdc= 427, f= 420, upm= 25200
.DW 37647 ; nAdc= 428, f= 425, upm= 25500
.DW 37209 ; nAdc= 429, f= 430, upm= 25800
.DW 36782 ; nAdc= 430, f= 435, upm= 26100
.DW 36364 ; nAdc= 431, f= 440, upm= 26400
.DW 35955 ; nAdc= 432, f= 445, upm= 26700
.DW 35556 ; nAdc= 433, f= 449,99, upm= 27000
.DW 35165 ; nAdc= 434, f= 455, upm= 27300
.DW 34783 ; nAdc= 435, f= 459,99, upm= 27600
.DW 34409 ; nAdc= 436, f= 464,99, upm= 27900
.DW 34043 ; nAdc= 437, f= 469,99, upm= 28200
.DW 33684 ; nAdc= 438, f= 475, upm= 28500
.DW 33333 ; nAdc= 439, f= 480, upm= 28800
.DW 32990 ; nAdc= 440, f= 485, upm= 29100
.DW 32653 ; nAdc= 441, f= 490, upm= 29400
.DW 32323 ; nAdc= 442, f= 495, upm= 29700
.DW 32000 ; nAdc= 443, f= 500, upm= 30000
.DW 31683 ; nAdc= 444, f= 505, upm= 30300
.DW 31373 ; nAdc= 445, f= 509,99, upm= 30600
.DW 31068 ; nAdc= 446, f= 515, upm= 30900
.DW 30769 ; nAdc= 447, f= 520, upm= 31200
.DW 30476 ; nAdc= 448, f= 525, upm= 31500
.DW 30189 ; nAdc= 449, f= 529,99, upm= 31800
.DW 29907 ; nAdc= 450, f= 534,99, upm= 32100
.DW 29630 ; nAdc= 451, f= 539,99, upm= 32400
.DW 29358 ; nAdc= 452, f= 545, upm= 32700
.DW 29091 ; nAdc= 453, f= 550, upm= 33000
.DW 28829 ; nAdc= 454, f= 555, upm= 33300
.DW 28571 ; nAdc= 455, f= 560,01, upm= 33601
.DW 28319 ; nAdc= 456, f= 564,99, upm= 33900
.DW 28070 ; nAdc= 457, f= 570, upm= 34200
.DW 27826 ; nAdc= 458, f= 575, upm= 34500
.DW 27586 ; nAdc= 459, f= 580, upm= 34800
.DW 27350 ; nAdc= 460, f= 585,01, upm= 35101
.DW 27119 ; nAdc= 461, f= 589,99, upm= 35400
.DW 26891 ; nAdc= 462, f= 594,99, upm= 35700
.DW 26667 ; nAdc= 463, f= 599,99, upm= 36000
.DW 26446 ; nAdc= 464, f= 605,01, upm= 36300
.DW 26230 ; nAdc= 465, f= 609,99, upm= 36599
.DW 26016 ; nAdc= 466, f= 615,01, upm= 36900
.DW 25806 ; nAdc= 467, f= 620,01, upm= 37201
.DW 25600 ; nAdc= 468, f= 625, upm= 37500
.DW 25397 ; nAdc= 469, f= 630, upm= 37800
.DW 25197 ; nAdc= 470, f= 635, upm= 38100
.DW 25000 ; nAdc= 471, f= 640, upm= 38400
.DW 24806 ; nAdc= 472, f= 645,01, upm= 38700
.DW 24615 ; nAdc= 473, f= 650,01, upm= 39001
.DW 24427 ; nAdc= 474, f= 655,01, upm= 39301
.DW 24242 ; nAdc= 475, f= 660,01, upm= 39601
.DW 24060 ; nAdc= 476, f= 665, upm= 39900
.DW 23881 ; nAdc= 477, f= 669,99, upm= 40199
.DW 23704 ; nAdc= 478, f= 674,99, upm= 40499
.DW 23529 ; nAdc= 479, f= 680,01, upm= 40801
.DW 23358 ; nAdc= 480, f= 684,99, upm= 41099
.DW 23188 ; nAdc= 481, f= 690,01, upm= 41401
.DW 23022 ; nAdc= 482, f= 694,99, upm= 41699
.DW 22857 ; nAdc= 483, f= 700, upm= 42000
.DW 22695 ; nAdc= 484, f= 705, upm= 42300
.DW 22535 ; nAdc= 485, f= 710,01, upm= 42600
.DW 22378 ; nAdc= 486, f= 714,99, upm= 42899
.DW 22222 ; nAdc= 487, f= 720,01, upm= 43200
.DW 22069 ; nAdc= 488, f= 725, upm= 43500
.DW 21918 ; nAdc= 489, f= 729,99, upm= 43800
.DW 21769 ; nAdc= 490, f= 734,99, upm= 44099
.DW 21622 ; nAdc= 491, f= 739,99, upm= 44399
.DW 21477 ; nAdc= 492, f= 744,98, upm= 44699
.DW 21333 ; nAdc= 493, f= 750,01, upm= 45001
.DW 21192 ; nAdc= 494, f= 755, upm= 45300
.DW 21053 ; nAdc= 495, f= 759,99, upm= 45599
.DW 20915 ; nAdc= 496, f= 765, upm= 45900
.DW 20779 ; nAdc= 497, f= 770,01, upm= 46200
.DW 20645 ; nAdc= 498, f= 775,01, upm= 46500
.DW 20513 ; nAdc= 499, f= 779,99, upm= 46800
.DW 20382 ; nAdc= 500, f= 785,01, upm= 47100
.DW 20253 ; nAdc= 501, f= 790,01, upm= 47400
.DW 20126 ; nAdc= 502, f= 794,99, upm= 47699
.DW 20000 ; nAdc= 503, f= 800, upm= 48000
.DW 19876 ; nAdc= 504, f= 804,99, upm= 48299
.DW 19753 ; nAdc= 505, f= 810, upm= 48600
.DW 19632 ; nAdc= 506, f= 815, upm= 48900
.DW 19512 ; nAdc= 507, f= 820,01, upm= 49200
.DW 19394 ; nAdc= 508, f= 825, upm= 49500
.DW 19277 ; nAdc= 509, f= 830, upm= 49800
.DW 19162 ; nAdc= 510, f= 834,99, upm= 50099
.DW 19048 ; nAdc= 511, f= 839,98, upm= 50399
.DW 18935 ; nAdc= 512, f= 845, upm= 50700
.DW 18824 ; nAdc= 513, f= 849,98, upm= 50999
.DW 18713 ; nAdc= 514, f= 855,02, upm= 51301
.DW 18605 ; nAdc= 515, f= 859,98, upm= 51599
.DW 18497 ; nAdc= 516, f= 865,01, upm= 51900
.DW 18391 ; nAdc= 517, f= 869,99, upm= 52199
.DW 18286 ; nAdc= 518, f= 874,99, upm= 52499
.DW 18182 ; nAdc= 519, f= 879,99, upm= 52799
.DW 18079 ; nAdc= 520, f= 885, upm= 53100
.DW 17978 ; nAdc= 521, f= 889,98, upm= 53399
.DW 17877 ; nAdc= 522, f= 895, upm= 53700
.DW 17778 ; nAdc= 523, f= 899,99, upm= 53999
.DW 17680 ; nAdc= 524, f= 904,98, upm= 54299
.DW 17582 ; nAdc= 525, f= 910,02, upm= 54601
.DW 17486 ; nAdc= 526, f= 915,02, upm= 54901
.DW 17391 ; nAdc= 527, f= 920,02, upm= 55201
.DW 17297 ; nAdc= 528, f= 925,02, upm= 55501
.DW 17204 ; nAdc= 529, f= 930,02, upm= 55801
.DW 17112 ; nAdc= 530, f= 935,02, upm= 56101
.DW 17021 ; nAdc= 531, f= 940,02, upm= 56401
.DW 16931 ; nAdc= 532, f= 945,01, upm= 56701
.DW 16842 ; nAdc= 533, f= 950,01, upm= 57000
.DW 16754 ; nAdc= 534, f= 955, upm= 57300
.DW 16667 ; nAdc= 535, f= 959,98, upm= 57599
.DW 16580 ; nAdc= 536, f= 965,02, upm= 57901
.DW 16495 ; nAdc= 537, f= 969,99, upm= 58199
.DW 16410 ; nAdc= 538, f= 975,02, upm= 58501
.DW 16327 ; nAdc= 539, f= 979,97, upm= 58798
.DW 16244 ; nAdc= 540, f= 984,98, upm= 59099
.DW 16162 ; nAdc= 541, f= 989,98, upm= 59399
.DW 16080 ; nAdc= 542, f= 995,02, upm= 59701
.DW 16000 ; nAdc= 543, f= 1000, upm= 60000
.DW 15238 ; nAdc= 544, f= 1050,01
.DW 14545 ; nAdc= 545, f= 1100,03
.DW 13913 ; nAdc= 546, f= 1150
.DW 13333 ; nAdc= 547, f= 1200,03
.DW 12800 ; nAdc= 548, f= 1250
.DW 12308 ; nAdc= 549, f= 1299,97
.DW 11852 ; nAdc= 550, f= 1349,98
.DW 11429 ; nAdc= 551, f= 1399,95
.DW 11034 ; nAdc= 552, f= 1450,06
.DW 10667 ; nAdc= 553, f= 1499,95
.DW 10323 ; nAdc= 554, f= 1549,94
.DW 10000 ; nAdc= 555, f= 1600
.DW 9697 ; nAdc= 556, f= 1649,99
.DW 9412 ; nAdc= 557, f= 1699,96
.DW 9143 ; nAdc= 558, f= 1749,97
.DW 8889 ; nAdc= 559, f= 1799,98
.DW 8649 ; nAdc= 560, f= 1849,92
.DW 8421 ; nAdc= 561, f= 1900,01
.DW 8205 ; nAdc= 562, f= 1950,03
.DW 8000 ; nAdc= 563, f= 2000
.DW 7805 ; nAdc= 564, f= 2049,97
.DW 7619 ; nAdc= 565, f= 2100,01
.DW 7442 ; nAdc= 566, f= 2149,96
.DW 7273 ; nAdc= 567, f= 2199,92
.DW 7111 ; nAdc= 568, f= 2250,04
.DW 6957 ; nAdc= 569, f= 2299,84
.DW 6809 ; nAdc= 570, f= 2349,83
.DW 6667 ; nAdc= 571, f= 2399,88
.DW 6531 ; nAdc= 572, f= 2449,85
.DW 6400 ; nAdc= 573, f= 2500
.DW 6275 ; nAdc= 574, f= 2549,8
.DW 6154 ; nAdc= 575, f= 2599,94
.DW 6038 ; nAdc= 576, f= 2649,88
.DW 5926 ; nAdc= 577, f= 2699,97
.DW 5818 ; nAdc= 578, f= 2750,09
.DW 5714 ; nAdc= 579, f= 2800,14
.DW 5614 ; nAdc= 580, f= 2850,02
.DW 5517 ; nAdc= 581, f= 2900,13
.DW 5424 ; nAdc= 582, f= 2949,85
.DW 5333 ; nAdc= 583, f= 3000,19
.DW 5246 ; nAdc= 584, f= 3049,94
.DW 5161 ; nAdc= 585, f= 3100,17
.DW 5079 ; nAdc= 586, f= 3150,23
.DW 5000 ; nAdc= 587, f= 3200
.DW 4923 ; nAdc= 588, f= 3250,05
.DW 4848 ; nAdc= 589, f= 3300,33
.DW 4776 ; nAdc= 590, f= 3350,08
.DW 4706 ; nAdc= 591, f= 3399,92
.DW 4638 ; nAdc= 592, f= 3449,76
.DW 4571 ; nAdc= 593, f= 3500,33
.DW 4507 ; nAdc= 594, f= 3550,03
.DW 4444 ; nAdc= 595, f= 3600,36
.DW 4384 ; nAdc= 596, f= 3649,64
.DW 4324 ; nAdc= 597, f= 3700,28
.DW 4267 ; nAdc= 598, f= 3749,71
.DW 4211 ; nAdc= 599, f= 3799,57
.DW 4156 ; nAdc= 600, f= 3849,86
.DW 4103 ; nAdc= 601, f= 3899,59
.DW 4051 ; nAdc= 602, f= 3949,64
.DW 4000 ; nAdc= 603, f= 4000
.DW 3951 ; nAdc= 604, f= 4049,61
.DW 3902 ; nAdc= 605, f= 4100,46
.DW 3855 ; nAdc= 606, f= 4150,45
.DW 3810 ; nAdc= 607, f= 4199,48
.DW 3765 ; nAdc= 608, f= 4249,67
.DW 3721 ; nAdc= 609, f= 4299,92
.DW 3678 ; nAdc= 610, f= 4350,19
.DW 3636 ; nAdc= 611, f= 4400,44
.DW 3596 ; nAdc= 612, f= 4449,39
.DW 3556 ; nAdc= 613, f= 4499,44
.DW 3516 ; nAdc= 614, f= 4550,63
.DW 3478 ; nAdc= 615, f= 4600,35
.DW 3441 ; nAdc= 616, f= 4649,81
.DW 3404 ; nAdc= 617, f= 4700,35
.DW 3368 ; nAdc= 618, f= 4750,59
.DW 3333 ; nAdc= 619, f= 4800,48
.DW 3299 ; nAdc= 620, f= 4849,95
.DW 3265 ; nAdc= 621, f= 4900,46
.DW 3232 ; nAdc= 622, f= 4950,5
.DW 3200 ; nAdc= 623, f= 5000
.DW 3168 ; nAdc= 624, f= 5050,51
.DW 3137 ; nAdc= 625, f= 5100,41
.DW 3107 ; nAdc= 626, f= 5149,66
.DW 3077 ; nAdc= 627, f= 5199,87
.DW 3048 ; nAdc= 628, f= 5249,34
.DW 3019 ; nAdc= 629, f= 5299,77
.DW 2991 ; nAdc= 630, f= 5349,38
.DW 2963 ; nAdc= 631, f= 5399,93
.DW 2936 ; nAdc= 632, f= 5449,59
.DW 2909 ; nAdc= 633, f= 5500,17
.DW 2883 ; nAdc= 634, f= 5549,77
.DW 2857 ; nAdc= 635, f= 5600,28
.DW 2832 ; nAdc= 636, f= 5649,72
.DW 2807 ; nAdc= 637, f= 5700,04
.DW 2783 ; nAdc= 638, f= 5749,19
.DW 2759 ; nAdc= 639, f= 5799,2
.DW 2735 ; nAdc= 640, f= 5850,09
.DW 2712 ; nAdc= 641, f= 5899,71
.DW 2689 ; nAdc= 642, f= 5950,17
.DW 2667 ; nAdc= 643, f= 5999,25
.DW 2645 ; nAdc= 644, f= 6049,15
.DW 2623 ; nAdc= 645, f= 6099,89
.DW 2602 ; nAdc= 646, f= 6149,12
.DW 2581 ; nAdc= 647, f= 6199,15
.DW 2560 ; nAdc= 648, f= 6250
.DW 2540 ; nAdc= 649, f= 6299,21
.DW 2520 ; nAdc= 650, f= 6349,21
.DW 2500 ; nAdc= 651, f= 6400
.DW 2481 ; nAdc= 652, f= 6449,01
.DW 2462 ; nAdc= 653, f= 6498,78
.DW 2443 ; nAdc= 654, f= 6549,32
.DW 2424 ; nAdc= 655, f= 6600,66
.DW 2406 ; nAdc= 656, f= 6650,04
.DW 2388 ; nAdc= 657, f= 6700,17
.DW 2370 ; nAdc= 658, f= 6751,05
.DW 2353 ; nAdc= 659, f= 6799,83
.DW 2336 ; nAdc= 660, f= 6849,32
.DW 2319 ; nAdc= 661, f= 6899,53
.DW 2302 ; nAdc= 662, f= 6950,48
.DW 2286 ; nAdc= 663, f= 6999,13
.DW 2270 ; nAdc= 664, f= 7048,46
.DW 2254 ; nAdc= 665, f= 7098,49
.DW 2238 ; nAdc= 666, f= 7149,24
.DW 2222 ; nAdc= 667, f= 7200,72
.DW 2207 ; nAdc= 668, f= 7249,66
.DW 2192 ; nAdc= 669, f= 7299,27
.DW 2177 ; nAdc= 670, f= 7349,56
.DW 2162 ; nAdc= 671, f= 7400,56
.DW 2148 ; nAdc= 672, f= 7448,79
.DW 2133 ; nAdc= 673, f= 7501,17
.DW 2119 ; nAdc= 674, f= 7550,73
.DW 2105 ; nAdc= 675, f= 7600,95
.DW 2092 ; nAdc= 676, f= 7648,18
.DW 2078 ; nAdc= 677, f= 7699,71
.DW 2065 ; nAdc= 678, f= 7748,18
.DW 2051 ; nAdc= 679, f= 7801,07
.DW 2038 ; nAdc= 680, f= 7850,83
.DW 2025 ; nAdc= 681, f= 7901,23
.DW 2013 ; nAdc= 682, f= 7948,34
.DW 2000 ; nAdc= 683, f= 8000
.DW 1988 ; nAdc= 684, f= 8048,29
.DW 1975 ; nAdc= 685, f= 8101,27
.DW 1963 ; nAdc= 686, f= 8150,79
.DW 1951 ; nAdc= 687, f= 8200,92
.DW 1939 ; nAdc= 688, f= 8251,68
.DW 1928 ; nAdc= 689, f= 8298,76
.DW 1916 ; nAdc= 690, f= 8350,73
.DW 1905 ; nAdc= 691, f= 8398,95
.DW 1893 ; nAdc= 692, f= 8452,19
.DW 1882 ; nAdc= 693, f= 8501,59
.DW 1871 ; nAdc= 694, f= 8551,58
.DW 1860 ; nAdc= 695, f= 8602,15
.DW 1850 ; nAdc= 696, f= 8648,65
.DW 1839 ; nAdc= 697, f= 8700,38
.DW 1829 ; nAdc= 698, f= 8747,95
.DW 1818 ; nAdc= 699, f= 8800,88
.DW 1808 ; nAdc= 700, f= 8849,56
.DW 1798 ; nAdc= 701, f= 8898,78
.DW 1788 ; nAdc= 702, f= 8948,55
.DW 1778 ; nAdc= 703, f= 8998,88
.DW 1768 ; nAdc= 704, f= 9049,77
.DW 1758 ; nAdc= 705, f= 9101,25
.DW 1749 ; nAdc= 706, f= 9148,08
.DW 1739 ; nAdc= 707, f= 9200,69
.DW 1730 ; nAdc= 708, f= 9248,55
.DW 1720 ; nAdc= 709, f= 9302,33
.DW 1711 ; nAdc= 710, f= 9351,26
.DW 1702 ; nAdc= 711, f= 9400,71
.DW 1693 ; nAdc= 712, f= 9450,68
.DW 1684 ; nAdc= 713, f= 9501,19
.DW 1675 ; nAdc= 714, f= 9552,24
.DW 1667 ; nAdc= 715, f= 9598,08
.DW 1658 ; nAdc= 716, f= 9650,18
.DW 1649 ; nAdc= 717, f= 9702,85
.DW 1641 ; nAdc= 718, f= 9750,15
.DW 1633 ; nAdc= 719, f= 9797,92
.DW 1624 ; nAdc= 720, f= 9852,22
.DW 1616 ; nAdc= 721, f= 9900,99
.DW 1608 ; nAdc= 722, f= 9950,25
.DW 1600 ; nAdc= 723, f= 10000
.DW 1524 ; nAdc= 724, f= 10498,69
.DW 1455 ; nAdc= 725, f= 10996,56
.DW 1391 ; nAdc= 726, f= 11502,52
.DW 1333 ; nAdc= 727, f= 12003
.DW 1280 ; nAdc= 728, f= 12500
.DW 1231 ; nAdc= 729, f= 12997,56
.DW 1185 ; nAdc= 730, f= 13502,11
.DW 1143 ; nAdc= 731, f= 13998,25
.DW 1103 ; nAdc= 732, f= 14505,89
.DW 1067 ; nAdc= 733, f= 14995,31
.DW 1032 ; nAdc= 734, f= 15503,88
.DW 1000 ; nAdc= 735, f= 16000
.DW 970 ; nAdc= 736, f= 16494,85
.DW 941 ; nAdc= 737, f= 17003,19
.DW 914 ; nAdc= 738, f= 17505,47
.DW 889 ; nAdc= 739, f= 17997,75
.DW 865 ; nAdc= 740, f= 18497,11
.DW 842 ; nAdc= 741, f= 19002,38
.DW 821 ; nAdc= 742, f= 19488,43
.DW 800 ; nAdc= 743, f= 20000
.DW 780 ; nAdc= 744, f= 20512,82
.DW 762 ; nAdc= 745, f= 20997,38
.DW 744 ; nAdc= 746, f= 21505,38
.DW 727 ; nAdc= 747, f= 22008,25
.DW 711 ; nAdc= 748, f= 22503,52
.DW 696 ; nAdc= 749, f= 22988,51
.DW 681 ; nAdc= 750, f= 23494,86
.DW 667 ; nAdc= 751, f= 23988,01
.DW 653 ; nAdc= 752, f= 24502,3
.DW 640 ; nAdc= 753, f= 25000
.DW 627 ; nAdc= 754, f= 25518,34
.DW 615 ; nAdc= 755, f= 26016,26
.DW 604 ; nAdc= 756, f= 26490,07
.DW 593 ; nAdc= 757, f= 26981,45
.DW 582 ; nAdc= 758, f= 27491,41
.DW 571 ; nAdc= 759, f= 28021,02
.DW 561 ; nAdc= 760, f= 28520,5
.DW 552 ; nAdc= 761, f= 28985,51
.DW 542 ; nAdc= 762, f= 29520,3
.DW 533 ; nAdc= 763, f= 30018,76
.DW 525 ; nAdc= 764, f= 30476,19
.DW 516 ; nAdc= 765, f= 31007,75
.DW 508 ; nAdc= 766, f= 31496,06
.DW 500 ; nAdc= 767, f= 32000
.DW 492 ; nAdc= 768, f= 32520,33
.DW 485 ; nAdc= 769, f= 32989,69
.DW 478 ; nAdc= 770, f= 33472,8
.DW 471 ; nAdc= 771, f= 33970,28
.DW 464 ; nAdc= 772, f= 34482,76
.DW 457 ; nAdc= 773, f= 35010,94
.DW 451 ; nAdc= 774, f= 35476,72
.DW 444 ; nAdc= 775, f= 36036,04
.DW 438 ; nAdc= 776, f= 36529,68
.DW 432 ; nAdc= 777, f= 37037,04
.DW 427 ; nAdc= 778, f= 37470,73
.DW 421 ; nAdc= 779, f= 38004,75
.DW 416 ; nAdc= 780, f= 38461,54
.DW 410 ; nAdc= 781, f= 39024,39
.DW 405 ; nAdc= 782, f= 39506,17
.DW 400 ; nAdc= 783, f= 40000
.DW 395 ; nAdc= 784, f= 40506,33
.DW 390 ; nAdc= 785, f= 41025,64
.DW 386 ; nAdc= 786, f= 41450,78
.DW 381 ; nAdc= 787, f= 41994,75
.DW 376 ; nAdc= 788, f= 42553,19
.DW 372 ; nAdc= 789, f= 43010,75
.DW 368 ; nAdc= 790, f= 43478,26
.DW 364 ; nAdc= 791, f= 43956,04
.DW 360 ; nAdc= 792, f= 44444,44
.DW 356 ; nAdc= 793, f= 44943,82
.DW 352 ; nAdc= 794, f= 45454,55
.DW 348 ; nAdc= 795, f= 45977,01
.DW 344 ; nAdc= 796, f= 46511,63
.DW 340 ; nAdc= 797, f= 47058,82
.DW 337 ; nAdc= 798, f= 47477,74
.DW 333 ; nAdc= 799, f= 48048,05
.DW 330 ; nAdc= 800, f= 48484,85
.DW 327 ; nAdc= 801, f= 48929,66
.DW 323 ; nAdc= 802, f= 49535,6
.DW 320 ; nAdc= 803, f= 50000
.DW 317 ; nAdc= 804, f= 50473,19
.DW 314 ; nAdc= 805, f= 50955,41
.DW 311 ; nAdc= 806, f= 51446,95
.DW 308 ; nAdc= 807, f= 51948,05
.DW 305 ; nAdc= 808, f= 52459,02
.DW 302 ; nAdc= 809, f= 52980,13
.DW 299 ; nAdc= 810, f= 53511,71
.DW 296 ; nAdc= 811, f= 54054,05
.DW 294 ; nAdc= 812, f= 54421,77
.DW 291 ; nAdc= 813, f= 54982,82
.DW 288 ; nAdc= 814, f= 55555,56
.DW 286 ; nAdc= 815, f= 55944,06
.DW 283 ; nAdc= 816, f= 56537,1
.DW 281 ; nAdc= 817, f= 56939,5
.DW 278 ; nAdc= 818, f= 57553,96
.DW 276 ; nAdc= 819, f= 57971,01
.DW 274 ; nAdc= 820, f= 58394,16
.DW 271 ; nAdc= 821, f= 59040,59
.DW 269 ; nAdc= 822, f= 59479,55
.DW 267 ; nAdc= 823, f= 59925,09
.DW 264 ; nAdc= 824, f= 60606,06
.DW 262 ; nAdc= 825, f= 61068,7
.DW 260 ; nAdc= 826, f= 61538,46
.DW 258 ; nAdc= 827, f= 62015,5
.DW 256 ; nAdc= 828, f= 62500
.DW 254 ; nAdc= 829, f= 62992,13
.DW 252 ; nAdc= 830, f= 63492,06
.DW 250 ; nAdc= 831, f= 64000
.DW 248 ; nAdc= 832, f= 64516,13
.DW 246 ; nAdc= 833, f= 65040,65
.DW 244 ; nAdc= 834, f= 65573,77

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8_v1_freqtab.html (1 of 2)1/20/2009 7:58:16 PM


Signal Generator ATmega8

.DW 242 ; nAdc= 835, f= 66115,7


.DW 241 ; nAdc= 836, f= 66390,04
.DW 239 ; nAdc= 837, f= 66945,61
.DW 237 ; nAdc= 838, f= 67510,55
.DW 235 ; nAdc= 839, f= 68085,11
.DW 234 ; nAdc= 840, f= 68376,07
.DW 232 ; nAdc= 841, f= 68965,52
.DW 230 ; nAdc= 842, f= 69565,22
.DW 229 ; nAdc= 843, f= 69869
.DW 227 ; nAdc= 844, f= 70484,58
.DW 225 ; nAdc= 845, f= 71111,11
.DW 224 ; nAdc= 846, f= 71428,57
.DW 222 ; nAdc= 847, f= 72072,07
.DW 221 ; nAdc= 848, f= 72398,19
.DW 219 ; nAdc= 849, f= 73059,36
.DW 218 ; nAdc= 850, f= 73394,5
.DW 216 ; nAdc= 851, f= 74074,07
.DW 215 ; nAdc= 852, f= 74418,6
.DW 213 ; nAdc= 853, f= 75117,37
.DW 212 ; nAdc= 854, f= 75471,7
.DW 211 ; nAdc= 855, f= 75829,38
.DW 209 ; nAdc= 856, f= 76555,02
.DW 208 ; nAdc= 857, f= 76923,08
.DW 206 ; nAdc= 858, f= 77669,9
.DW 205 ; nAdc= 859, f= 78048,78
.DW 204 ; nAdc= 860, f= 78431,37
.DW 203 ; nAdc= 861, f= 78817,73
.DW 201 ; nAdc= 862, f= 79601,99
.DW 200 ; nAdc= 863, f= 80000
.DW 199 ; nAdc= 864, f= 80402,01
.DW 198 ; nAdc= 865, f= 80808,08
.DW 196 ; nAdc= 866, f= 81632,65
.DW 195 ; nAdc= 867, f= 82051,28
.DW 194 ; nAdc= 868, f= 82474,23
.DW 193 ; nAdc= 869, f= 82901,55
.DW 192 ; nAdc= 870, f= 83333,33
.DW 190 ; nAdc= 871, f= 84210,53
.DW 189 ; nAdc= 872, f= 84656,08
.DW 188 ; nAdc= 873, f= 85106,38
.DW 187 ; nAdc= 874, f= 85561,5
.DW 186 ; nAdc= 875, f= 86021,51
.DW 185 ; nAdc= 876, f= 86486,49
.DW 184 ; nAdc= 877, f= 86956,52
.DW 183 ; nAdc= 878, f= 87431,69
.DW 182 ; nAdc= 879, f= 87912,09
.DW 181 ; nAdc= 880, f= 88397,79
.DW 180 ; nAdc= 881, f= 88888,89
.DW 179 ; nAdc= 882, f= 89385,47
.DW 178 ; nAdc= 883, f= 89887,64
.DW 177 ; nAdc= 884, f= 90395,48
.DW 176 ; nAdc= 885, f= 90909,09
.DW 175 ; nAdc= 886, f= 91428,57
.DW 174 ; nAdc= 887, f= 91954,02
.DW 173 ; nAdc= 888, f= 92485,55
.DW 172 ; nAdc= 889, f= 93023,26
.DW 171 ; nAdc= 890, f= 93567,25
.DW 170 ; nAdc= 891, f= 94117,65
.DW 169 ; nAdc= 892, f= 94674,56
.DW 168 ; nAdc= 893, f= 95238,1
.DW 168 ; nAdc= 894, f= 95238,1
.DW 167 ; nAdc= 895, f= 95808,38
.DW 166 ; nAdc= 896, f= 96385,54
.DW 165 ; nAdc= 897, f= 96969,7
.DW 164 ; nAdc= 898, f= 97560,98
.DW 163 ; nAdc= 899, f= 98159,51
.DW 162 ; nAdc= 900, f= 98765,43
.DW 162 ; nAdc= 901, f= 98765,43
.DW 161 ; nAdc= 902, f= 99378,88
.DW 160 ; nAdc= 903, f= 100000
.DW 152 ; nAdc= 904, f= 105263,16
.DW 145 ; nAdc= 905, f= 110344,83
.DW 139 ; nAdc= 906, f= 115107,91
.DW 133 ; nAdc= 907, f= 120300,75
.DW 128 ; nAdc= 908, f= 125000
.DW 123 ; nAdc= 909, f= 130081,3
.DW 119 ; nAdc= 910, f= 134453,78
.DW 116 ; nAdc= 911, f= 137931,03
.DW 113 ; nAdc= 912, f= 141592,92
.DW 112 ; nAdc= 913, f= 142857,14
.DW 111 ; nAdc= 914, f= 144144,14
.DW 110 ; nAdc= 915, f= 145454,55
.DW 109 ; nAdc= 916, f= 146788,99
.DW 108 ; nAdc= 917, f= 148148,15
.DW 107 ; nAdc= 918, f= 149532,71
.DW 106 ; nAdc= 919, f= 150943,4
.DW 105 ; nAdc= 920, f= 152380,95
.DW 104 ; nAdc= 921, f= 153846,15
.DW 103 ; nAdc= 922, f= 155339,81
.DW 102 ; nAdc= 923, f= 156862,75
.DW 101 ; nAdc= 924, f= 158415,84
.DW 100 ; nAdc= 925, f= 160000
.DW 99 ; nAdc= 926, f= 161616,16
.DW 98 ; nAdc= 927, f= 163265,31
.DW 97 ; nAdc= 928, f= 164948,45
.DW 96 ; nAdc= 929, f= 166666,67
.DW 95 ; nAdc= 930, f= 168421,05
.DW 94 ; nAdc= 931, f= 170212,77
.DW 93 ; nAdc= 932, f= 172043,01
.DW 92 ; nAdc= 933, f= 173913,04
.DW 91 ; nAdc= 934, f= 175824,18
.DW 90 ; nAdc= 935, f= 177777,78
.DW 89 ; nAdc= 936, f= 179775,28
.DW 88 ; nAdc= 937, f= 181818,18
.DW 87 ; nAdc= 938, f= 183908,05
.DW 86 ; nAdc= 939, f= 186046,51
.DW 85 ; nAdc= 940, f= 188235,29
.DW 84 ; nAdc= 941, f= 190476,19
.DW 83 ; nAdc= 942, f= 192771,08
.DW 82 ; nAdc= 943, f= 195121,95
.DW 81 ; nAdc= 944, f= 197530,86
.DW 80 ; nAdc= 945, f= 200000
.DW 79 ; nAdc= 946, f= 202531,65
.DW 78 ; nAdc= 947, f= 205128,21
.DW 77 ; nAdc= 948, f= 207792,21
.DW 76 ; nAdc= 949, f= 210526,32
.DW 75 ; nAdc= 950, f= 213333,33
.DW 74 ; nAdc= 951, f= 216216,22
.DW 73 ; nAdc= 952, f= 219178,08
.DW 72 ; nAdc= 953, f= 222222,22
.DW 71 ; nAdc= 954, f= 225352,11
.DW 70 ; nAdc= 955, f= 228571,43
.DW 69 ; nAdc= 956, f= 231884,06
.DW 68 ; nAdc= 957, f= 235294,12
.DW 67 ; nAdc= 958, f= 238805,97
.DW 66 ; nAdc= 959, f= 242424,24
.DW 65 ; nAdc= 960, f= 246153,85
.DW 64 ; nAdc= 961, f= 250000
.DW 63 ; nAdc= 962, f= 253968,25
.DW 62 ; nAdc= 963, f= 258064,52
.DW 61 ; nAdc= 964, f= 262295,08
.DW 60 ; nAdc= 965, f= 266666,67
.DW 59 ; nAdc= 966, f= 271186,44
.DW 58 ; nAdc= 967, f= 275862,07
.DW 57 ; nAdc= 968, f= 280701,75
.DW 56 ; nAdc= 969, f= 285714,29
.DW 55 ; nAdc= 970, f= 290909,09
.DW 54 ; nAdc= 971, f= 296296,3
.DW 53 ; nAdc= 972, f= 301886,79
.DW 52 ; nAdc= 973, f= 307692,31
.DW 51 ; nAdc= 974, f= 313725,49
.DW 50 ; nAdc= 975, f= 320000
.DW 49 ; nAdc= 976, f= 326530,61
.DW 48 ; nAdc= 977, f= 333333,33
.DW 47 ; nAdc= 978, f= 340425,53
.DW 46 ; nAdc= 979, f= 347826,09
.DW 45 ; nAdc= 980, f= 355555,56
.DW 44 ; nAdc= 981, f= 363636,36
.DW 43 ; nAdc= 982, f= 372093,02
.DW 42 ; nAdc= 983, f= 380952,38
.DW 41 ; nAdc= 984, f= 390243,9
.DW 40 ; nAdc= 985, f= 400000
.DW 39 ; nAdc= 986, f= 410256,41
.DW 38 ; nAdc= 987, f= 421052,63
.DW 37 ; nAdc= 988, f= 432432,43
.DW 36 ; nAdc= 989, f= 444444,44
.DW 35 ; nAdc= 990, f= 457142,86
.DW 34 ; nAdc= 991, f= 470588,24
.DW 33 ; nAdc= 992, f= 484848,48
.DW 32 ; nAdc= 993, f= 500000
.DW 31 ; nAdc= 994, f= 516129,03
.DW 30 ; nAdc= 995, f= 533333,33
.DW 29 ; nAdc= 996, f= 551724,14
.DW 28 ; nAdc= 997, f= 571428,57
.DW 27 ; nAdc= 998, f= 592592,59
.DW 26 ; nAdc= 999, f= 615384,62
.DW 25 ; nAdc= 1000, f= 640000
.DW 24 ; nAdc= 1001, f= 666666,67
.DW 23 ; nAdc= 1002, f= 695652,17
.DW 22 ; nAdc= 1003, f= 727272,73
.DW 21 ; nAdc= 1004, f= 761904,76
.DW 20 ; nAdc= 1005, f= 800000
.DW 19 ; nAdc= 1006, f= 842105,26
.DW 18 ; nAdc= 1007, f= 888888,89
.DW 17 ; nAdc= 1008, f= 941176,47
.DW 16 ; nAdc= 1009, f= 1000000
.DW 15 ; nAdc= 1010, f= 1066666,67
.DW 14 ; nAdc= 1011, f= 1142857,14
.DW 13 ; nAdc= 1012, f= 1230769,23
.DW 12 ; nAdc= 1013, f= 1333333,33
.DW 11 ; nAdc= 1014, f= 1454545,45
.DW 10 ; nAdc= 1015, f= 1600000
.DW 9 ; nAdc= 1016, f= 1777777,78
.DW 8 ; nAdc= 1017, f= 2000000
.DW 7 ; nAdc= 1018, f= 2285714,29
.DW 6 ; nAdc= 1019, f= 2666666,67
.DW 5 ; nAdc= 1020, f= 3200000
.DW 4 ; nAdc= 1021, f= 4000000
.DW 3 ; nAdc= 1022, f= 5333333,33
.DW 2 ; nAdc= 1023, f= 8000000

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/signalgen/rectgen_m8_v1_freqtab.html (2 of 2)1/20/2009 7:58:16 PM


40 MHz-Frequency counter with an ATmega8, source code

Pfad: Home => AVR-Overview => Applications => Frequency counter => Software

Software for the


Frequency counter

; *******************************************************
; * Frequencycounter, RPM-Meter and Voltmeter *
; * for ATmega8 at 16 MHz crystal clock frequency *
; * with prescaler /1 or /16 *
; * Version 0.3 (C)2009 by info!at!avr-asm-tutorial.net *
; *******************************************************
;
.INCLUDE "m8def.inc"
;
.EQU debug = 0
.EQU debugpulse = 0
;
; Switches for connected hardware
;
.EQU cDisplay = 1 ; LCD display connected
.EQU cDisplay8 = 0 ; displays 8 characters per line instead of 16
.EQU cDisplay2 = 1 ; two line LCD display connected
.EQU cUart = 1 ; Uart active
; attached prescaler on port C
.EQU pPresc = PORTC ; prescaler by 16 output attached to port C
.EQU pPrescD = DDRC ; data direction of prescaler
.EQU bPresc = 5 ; bit 5 enables prescaler by 16
;
; ================================================
; Other hardware depending stuff
; ================================================
;
.EQU cFreq = 16000000 ; Clock frequency processor in cycles/s
.IF cUart
.EQU cBaud = 9600 ; If Uart active, define Baudrate
.ENDIF
.EQU bLcdE = 5 ; LCD E port bit on Port B
.EQU bLcdRs = 4 ; Lcd RS port bit on Port B
;
; ================================================
; Constants for voltage measurement
; ================================================
;
; Resistor network as pre-divider for the ADC
; --------------------------------------
; R1 R2(k) Meas Accur. MaxVoltage
; kOhm kOhm Volt mV/dig Volt
; --------------------------------------
; 1000 1000 5,12 5 10
; 1000 820 5,68 6 11
; 1000 680 6,32 6 12
; 1000 560 7,13 7 14
; 1000 470 8,01 8 15
; 1000 330 10,32 10 20
; 1000 270 12,04 12 23
; 1000 220 14,20 14 27
; 1000 180 16,78 16 32
; 1000 150 19,63 19 38
; 1000 120 23,98 23 46
; 1000 100 28,16 28 55
;
.EQU cR1 = 1000 ; Resistor between ADC input and measured voltage
.EQU cR2 = 1000 ; Resistor between ADC input and ground
.EQU cRin = 8250 ; Input resistance ADC, experimental
;
; Other sSoft switches
;
.EQU cNMode = 3 ; number of measurements before mode changes
.EQU cDecSep = '.' ; decimal separator for numbers displayed
.EQU c1kSep = ',' ; thousands separator
.EQU nMeasm = 4 ; number of measurements per second
.IF (nMeasm<4)||(nMeasm>7)
.ERROR "Number of measurements outside acceptable range"
.ENDIF
;
; ================================================
; Hardware connections
; ================================================
; ___ ___
; RESET |1 |_| 28| Prescaler divide by 16 output
; RXD |2 A 27|
; TXD |3 T 26|
; Time inp |4 M 25|
; |5 E 24| Mode select input, 0..2.56 V
; Count in |6 L 23| Voltage input, 0..2.56 V
; VCC |7 22| GND
; GND |8 A 21| AREF (+2.56 V, output)
; XTAL1 |9 T 20| AVCC input
; XTAL2 |10 m 19| SCK/LCD-E
; |11 e 18| MISO/LCD-RS
; |12 g 17| MOSI/LCD-D7
; |13 a 16| LCD-D6
; LCD-D4 |14 8 15| LCD-D5
; |_________|
;
;
; ================================================
; Derived constants
; ================================================
;
.EQU cR2c = (cR2 * cRin) / (cR2+cRin)
.EQU cMultiplier = (641 * (cR1+cR2c))/cR2c ; used for voltage
multiplication
.EQU cMaxVoltage = 1024*cMultiplier/256 ; in mV
.EQU cSafeVoltage = (cMaxVoltage * 5000) / 2560
.EQU cTDiv = 1000/nMeasm ; interval per measurement update
; calculating the CTC and prescaler values for TC1 (frequency
measurement)
.SET cCmp1F = cFreq/32 ; CTC compare value with counter prescaler =
8
.SET cPre1F = (1<<WGM12)|(1<<CS11) ; CTC and counter prescaler = 8
.IF cFreq>2097120
.SET cCmp1F = cFreq/256 ; CTC compare value with counter
prescaler = 64
.SET cPre1F = (1<<WGM12)|(1<<CS11)|(1<<CS10) ; counter
prescaler = 64
.ENDIF
.IF cFreq>16776960
.SET cCmp1F = cFreq/1024 ; CTC compare value with counter
prescaler = 256
.SET cPre1F = (1<<WGM12)|(1<<CS12) ; counter prescaler = 256
.ENDIF
; calculating the CTC and counter prescaler values for TC2 (LCD/
UART update)
.SET cCmp2 = cFreq/8000
.SET cPre2 = (1<<CS21) ; counter prescaler = 8
.IF cFreq>2040000
.SET cCmp2 = cFreq/32000
.SET cPre2 = (1<<CS21)|(1<<CS20) ; counter prescaler = 32
.ENDIF
.IF cFreq>8160000
.SET cCmp2 = cFreq/64000
.SET cPre2 = (1<<CS22) ; counter prescaler = 64
.ENDIF
.IF cFreq>16320000
.SET cCmp2 = cFreq/128000 ; counter prescaler = 128
.SET cPre2 = (1<<CS22)|(1<<CS20)
.ENDIF
;
; Uart constants
;
.IF cUart
.EQU cNul = $00
.EQU cClrScr = $0C
.EQU cCr = $0D
.EQU cLf = $0A
.ENDIF
;
; Debug definitions for testing
;
; (none)
;
; ================================================
; Register definitons
; ================================================
;
; R0 used for LPM and for calculation purposes
.DEF rRes1 = R1 ; Result byte 1
.DEF rRes2 = R2 ; Result byte 2
.DEF rRes3 = R3 ; Result byte 3
.DEF rRes4 = R4 ; Result byte 4
.DEF rDiv1 = R5 ; Divisor byte 1
.DEF rDiv2 = R6 ; Divisor byte 2
.DEF rDiv3 = R7 ; Divisor byte 3
.DEF rDiv4 = R8 ; Divisor byte 4
.DEF rCpy1 = R9 ; Copy byte 1
.DEF rCpy2 = R10 ; Copy byte 2
.DEF rCpy3 = R11 ; Copy byte 3
.DEF rCpy4 = R12 ; Copy byte 4
.DEF rCtr1 = R13 ; Counter/Timer byte 1
.DEF rCtr2 = R14 ; Counter/Timer byte 2
.DEF rCtr3 = R15 ; Counter/Timer byte 3
.DEF rmp = R16 ; Multipurpose register outside interrupts
.DEF rimp = R17 ; Multipurpose register inside interrupts
.DEF rSreg = R18 ; Save status register inside interrupts
.DEF rTDiv = R19 ; Internal divider for TC2 count down
.DEF rMode = R20 ; Current mode of operation
.DEF rNMode = R21 ; Number of inadequate measurements
.DEF rir = R22 ; interrim calculation register
.DEF rFlg = R23 ; Flag register
.EQU bCyc = 2 ; measure cycle ended
.EQU bMode = 3 ; measuring mode, 1 = frequency, 0 = time
.EQU bEdge = 4 ; measured edge, 1 = rising, 0 = falling
.EQU bOvf = 5 ; overflow bit
.EQU bAdc = 6 ; ADC conversion complete flag bit
.EQU bUartRxLine = 7 ; Uart line complete flag bit
.DEF rDelL = R24 ; delay counter for LCD, LSB
.DEF rDelH = R25 ; dto., MSB
; X = R26..R27 used for calculation purposes
; Y = R28..R29: free
; Z = R30..R31 used for LPM and calculation purposes
;
; ================================================
; SRAM definitions
; ================================================
;
.DSEG
.ORG Sram_Start
;
; Result display space in SRAM
;
sResult:
.BYTE 32
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
;
.IF cUart
.EQU UartRxbLen = 38 ; Buffer length in bytes
;
sUartFlag: ; flag register for Uart
.BYTE 1
.EQU bUMonU = 0 ; displays voltage over Uart
.EQU bUMonF = 1 ; displays frequency over Uart
; free: bits 2..7
sUartMonUCnt: ; counter for Monitoring voltage
.BYTE 1
sUartMonURpt: ; counter preset for monitoring voltage
.BYTE 1
sUartMonFCnt: ; counter for Monitoring frequency
.BYTE 1
sUartMonFRpt: ; counter preset for monitoring voltage
.BYTE 1
sUartRxBp: ; buffer pointer
.BYTE 1
sUartRxBs: ; buffer
.BYTE UartRxbLen
sUartRxBe: ; buffer end
.ENDIF
;
; Main interval timer characteristics
;
sTMeas: ; ms per measuring interval (default: 250)
.BYTE 1
;
; ADC result
;
sAdc0L: ; ADC result, channel 0, LSB
.BYTE 1
sAdc0H: ; ADC result, channel 0, MSB
.BYTE 1
sAdc1L: ; ADC result, channel 1, LSB
.BYTE 1
sAdc1H: ; ADC result, channel 1, MSB
.BYTE 1
;
; Interim storage for counter value during time measurement
;
sCtr:
.BYTE 4
;
; ================================================
; Selected mode flags
; ================================================
;
; Mode Measuring Prescale Display
; ---------------------------------------------
; 0 Frequency 16 Frequency
; 1 Frequency 1 Frequency
; 2 Time HL 1 Frequency
; 3 Time HL 1 Rounds per Minute
; 4 Time HL 1 Time
; 5 Time H 1 Time
; 6 Time L 1 Time
; 7 PW ratio H 1 Pulse width ratio H %
; 8 PW ratio L 1 Pulse width ratio L %
; 9 none - Voltage only
; (for a single line LCD)
;
.EQU cModeFrequency16 = 0
.EQU cModeFrequency = 1
.EQU cModeTimeFreq = 2
.EQU cModeTimeRpm = 3
.EQU cModeTimeTimeHL = 4
.EQU cModeTimeTimeH = 5
.EQU cModeTimeTimeL = 6
.EQU cModeTimePwrH = 7
.EQU cModeTimePwrL = 8
.EQU cModeVoltage = 9
;
sModeSlct: ; Selected mode
.BYTE 1
sModeNext: ; next selected mode
.BYTE 1
;
; ==================================================
; Info on timer and counter interrupt operation
; ==================================================
;
; Clock => Presc2 => TC2 => CTC => rTDiv =>
; ADC0 conversion => ADC1 conversion => bAdc-flag
;
; Main interval timer TC2
; - uses TC2 as 8-bit-CTC, with compare interrupt
; - starts a ADC conversion
; - on ADC conversion complete:
; * store ADC result
; * convert ADC result
; * if a new counter result: convert this
; * if Uart connected and monitoring f/U: display on Uart
; * if LCD connected and display mode: display f/U result
;
; Operation at 16 MHz clock:
; cFreq => Prescaler/128 => CTC(125) => rTDiv(250)
; 16MHz => 125 kHz => 1 kHz => 4 Hz
;
; Frequeny counting modes (Mode = 0 and 1)
; - uses TC0 as 8-bit-counter to count positive edges
; - uses TC1 as 16-bit-counter to time-out the counter after 250
ms
;
; Timer modes (Mode = 2 to 8)
; - uses edge detection on external INT0 for timeout
; - uses TC1 as 16-bit-counter to time-out from edge to edge
;
; Voltage only (Mode = 9)
; - Timers TC0 and TC1 off
; - Timer TC2 times interval
;
; ==============================================
; Reset and Interrupt Vectors starting here
; ==============================================
;
.CSEG
.ORG $0000
;
; Reset/Intvectors
;
rjmp Main ; Reset
rjmp Int0Int; Int0
reti ; Int1
rjmp TC2CmpInt ; TC2 Comp
reti ; TC2 Ovf
reti ; TC1 Capt
rjmp Tc1CmpAInt ; TC1 Comp A
reti ; TC1 Comp B
rjmp Tc1OvfInt ; TC1 Ovf
rjmp TC0OvfInt ; TC0 Ovf
reti ; SPI STC
.IF cUart
rjmp SioRxcIsr ; USART RX
.ELSE
reti ; USART RX
.ENDIF
reti ; USART UDRE
reti ; USART TXC
rjmp AdcCcInt ; ADC Conv Compl
reti ; EERDY
reti ; ANA_COMP
reti ; TWI
reti ; SPM_RDY
;
; =============================================
;
; Interrupt Service Routines
;
; =============================================
;
; TC2 Compare Match Interrupt
; counts rTDiv down, if zero: starts an AD conversion
;
TC2CmpInt:
in rSreg,SREG ; save SREG
dec rTDiv ; count down
brne TC2CmpInt1 ; not zero, interval not ended
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|
(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start ADC conversion
lds rTDiv,sTMeas ; restart interval timer
TC2CmpInt1:
out SREG,rSreg ; restore SREG
reti
;
; External Interrupt INT0 Service Routine
; active in modes 2 to 6 (measuring the signal duration),
; detects positive going edges of the input
; INT1, TC1 is in free running mode,
; reads the current counter state of TC1,
; copies it to the result registers,
; clears the counter and restarts it
;
Int0Int:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for
copy
rjmp Int0Int1 ; 4, no, last result hasn't been read
in rCpy1,TCNT1L ; 4, read timer 1 LSB
in rCpy2,TCNT1H ; 5, dto., MSB
mov rCpy3,rCtr2 ; 6, copy the counter bytes
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
cbr rFlg,1<<bEdge ; 9, set falling edge
sbic PIND,2 ; 10/11, check if input = 0
sbr rFlg,1<<bEdge ; 11, no, set edge flag to rising
Int0Int1: ; 4/11
ldi rimp,0 ; 5/12, reset the timer
out TCNT1H,rimp ; 6/13, set TC1 zero to restart
out TCNT1L,rimp ; 7/14
mov rCtr1,rimp ; 8/15, clear the upper bytes
mov rCtr2,rimp ; 9/16
mov rCtr3,rimp ; 10/17
out SREG,rSreg ; 11/18, restore SREG
reti ; 15/22
;
; TC1 Compare Match A Interrupt Service Routine
; active in modes 0 and 1 (measuring the number of
; sigals on the T1 input), timeout every 0.25s,
; reads the counter TC0, copies the count to
; the result registers and clears TC0
;
Tc1CmpAInt:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for
copy
rjmp TC1CmpAInt1 ; 4, no, last result hasn't been read
in rCpy1,TCNT0 ; 4, read counter TC0
mov rCpy2,rCtr1 ; 5, copy counter bytes to result
mov rCpy3,rCtr2 ; 6
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
Tc1CmpAInt1: ; 4/8
ldi rimp,0 ; 5/9, clear counter
out TCNT0,rimp ; 6/10
mov rCtr1,rimp ; 7/11, clear counter bytes
mov rCtr2,rimp ; 8/12
mov rCtr3,rimp ; 9/13
out SREG,rSreg ; 10/14, restore SREG
reti ; 14/18
;
; TC1 Overflow Interrupt Service Routine
; active in modes 2 to 6 counting clock cycles to measure time
; increases the upper bytes and detects overflows
;
Tc1OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr2 ; 2, increase byte 3 of the counter
brne Tc1OvfInt1 ; 3/4, no overflow
inc rCtr3 ; 4, increase byte 4 of the counter
brne Tc1OvfInt1 ; 5/6, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 6, set overflow and end of
cycle bit
Tc1OvfInt1: ; 4/6
out SREG,rSreg ; 5/7, restore SREG
reti ; 9/11
;
; TC0 Overflow Interrupt Service Routine
; active in modes 0 and 1 counting positive edges on T1
; increases the upper bytes and detects overflows
;
Tc0OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr1 ; 2, increase byte 2 of the counter
brne Tc0OvfInt1 ; 3/4, no overflow
inc rCtr2 ; 4, increase byte 3 of the counter
brne Tc0OvfInt1 ; 5/6, no overflow
inc rCtr3 ; 6, increase byte 4 of the counter
brne Tc0OvfInt1 ; 7/8, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 8, set overflow bit
Tc0OvfInt1: ; 4/6/8
out SREG,rSreg ; 5/7/9, restore SREG
reti ; 9/11/13
;
; Uart RxC Interrupt Service Routine
; receives a character, signals errors, echoes it back,
; puts it into the SRAM line buffer, checks for carriage
; return characters, if yes echoes additional linefeed
; and sets line-complete flag
;
.IF cUart
SioRxCIsr:
in rSreg,SREG ; 1, Save SReg
in rimp,UCSRA ; 2, Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; 3, isolate error bits
in rimp,UDR ; 4, read character from UART
breq SioRxCIsr1 ; 5/6, no errors
ldi rimp,'*' ; 6, signal an error
out UDR,rimp ; 7
rjmp SioRxCIsr4 ; 9, return from int
SioRxCIsr1: ; 6
out UDR,rimp ; 7, echo the character
push ZH ; 9, Save Z register
push ZL ; 11
ldi ZH,HIGH(sUartRxBs) ; 12, Load Position for next RX char
lds ZL,sUartRxBp ; 14
st Z+,rimp ; 16, save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; 17, End of buffer?
brcc SioRxCIsr2 ; 18/19, Buffer overflow
sts sUartRxBp,ZL ; 20, Save next pointer position
SioRxCIsr2: ; 19/20
cpi rimp,cCr ; 20/21, Carriage Return?
brne SioRxCIsr3 ; 21/22/23, No, go on
ldi rimp,cLf ; 22/23, Echo linefeed
out UDR,rimp ; 23/24
sbr rFlg,(1<<bUartRxLine) ; 24/25, Set line complete flag
rjmp SioRxCIsr3a
SioRxCIsr3: ; 22/23/24/25
cpi rimp,cLf
brne SioRxCIsr3a
sbr rFlg,(1<<bUartRxLine)
SioRxCIsr3a:
pop ZL ; 24/25/26/27, restore Z-register
pop ZH ; 26/27/28/29
SioRxCIsr4: ; 9/26/27/28/29
out SREG,rSreg ; 10/27/28/29/30, restore SREG
reti ; 14/31/32/33/34, return from Int
.ENDIF
;
; ADC has completed a conversion
; used in all modes, ADC has completed a conversion
; if ADMUX channel is 0 then set ADMUX=1 and start
; another coversion
; if ADMUX channel is 1 he set ADMUX=0, disable the ADC
; and set teh ADC cycle end flag
;
.EQU cStopAdc = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
.EQU cStartAdc = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|cStopAdc
AdcCcInt:
in rSreg,SREG ; 1, save SREG
in rimp,ADMUX ; 2, read the current channel info
sbrc rimp,0 ; 3/4, jump if channel = 0
rjmp AdcCcInt1 ; 5
sbr rimp,1 ; 5, set channel MUX to one
out ADMUX,rimp ; 6
in rimp,ADCL ; 7, read result LSB
sts sAdc0L,rimp ; 9, store result LSB
in rimp,ADCH ; 10, read result MSB
sts sAdc0H,rimp ; 12, store result MSB
ldi rimp,cStartAdc
out ADCSRA,rimp ; 14, start next conversion
out SREG,rSreg ; 15, restore SREG
reti ; 19
AdcCcInt1: ; 5
cbr rimp,1 ; 6, set MUX to channel 0
out ADMUX,rimp ; 7
in rimp,ADCL ; 8, read result LSB
sts sAdc1L,rimp ; 10, store result LSB
in rimp,ADCH ; 11, read result MSB
sts sAdc1H,rimp ; 13, store result MSB
sbr rFlg,1<<bAdc ; 14, set flag bit
ldi rimp,cStopAdc ; 15, ADC off
out ADCSRA,rimp ; 16, switch ADC off
out SREG,rSreg ; 17, restore SREG
reti ; 21
;
; ================================================
; Common subroutines
; ================================================
;
; Setting timer/counter modes for measuring
;
SetModeNext:
rcall ClrTc ; clear the timers TC0 and TC1, disable INT0
lds rmp,sModeNext ; read next mode
mov rMode,rmp ; copy to current mode
ldi ZH,HIGH(SetModeTab)
ldi ZL,LOW(SetModeTab)
add ZL,rmp
ldi rmp,0
adc ZH,rmp
ijmp
; Table mode setting
SetModeTab:
rjmp SetMode0 ; f div 16, f
rjmp SetMode1 ; f, f
rjmp SetModeT ; t, f
rjmp SetModeT ; t, u
rjmp SetModeT ; t, t
rjmp SetModeE ; th, t
rjmp SetModeE ; tl, t
rjmp SetModeE ; th, p
rjmp SetModeE ; tl, p
ret ; U, U
;
; Set counters/timers to mode 0
; TC0 counts input signals (positive edges)
; TC1 times the gate at 250 ms
; INT0 disabled
;
SetMode0:
cbi pPresc,bPresc ; enable prescaler
rjmp SetModeF ; frequency measurement
;
; Set counters/timers to mode 1
;
SetMode1:
sbi pPresc,bPresc ; disable prescaler
; Set timer/counter mode to frequency measurement
SetModeF:
ldi rmp,HIGH(cCmp1F) ; set the compare match high value
out OCR1AH,rmp
ldi rmp,LOW(cCmp1F) ; set the compare match low value
out OCR1AL,rmp
ldi rmp,0xFF ; disable the compare match B
out OCR1BH,rmp
out OCR1BL,rmp
ldi rmp,0 ; CTC mode
out TCCR1A,rmp
ldi rmp,cPre1F ; set the prescaler value for TC1
out TCCR1B,rmp
ldi rmp,(1<<CS02)|(1<<CS01)|(1<<CS00) ; count rising edges
on T0
out TCCR0,rmp
ldi rmp,(1<<OCIE2)|(1<<OCIE1A)|(1<<TOIE0) ; enable TC2Cmp,
TC1CmpAInt and TC0OverflowInt
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement
;
SetModeT:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00) ; sleep enable,
positive edges on INT0 interrupt
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement, all edges
;
SetModeE:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC00) ; sleep enable, any logical
change on INT0 interrupts
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
;
; clears the timers and resets the upper bytes
;
ClrTc:
clr rmp ; disable INT0
out GICR,rmp
clr rmp ; stop the counters/timers
out TCCR0,rmp ; stop TC0 counting/timing
out TCCR1B,rmp ; stop TC1 counting/timing
out TCNT0,rmp ; clear TC0
out TCNT1L,rmp ; clear TC1
out TCNT1H,rmp
clr rCtr1 ; clear upper bytes
clr rCtr2
clr rCtr3
ldi rmp,1<<OCIE2 ; enable only output compare of TC2 ints
out TIMSK,rmp ; timer int disable
ret
;
; =======================================================
; Math routines
; =======================================================
;
; Divides cFreq/256 by the timer value in rDiv4:rDiv3:rDiv2:rDiv1
; yields frequency in R4:R3:R2:(Fract):R1
;
Divide:
clr rmp ; rmp:R0:ZH:ZL:XH:XL is divisor
clr R0
clr ZH
ldi ZL,BYTE3(cFreq/256) ; set divisor
ldi XH,BYTE2(cFreq/256)
ldi XL,BYTE1(cFreq/256)
clr rRes1 ; set result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
Divide1:
lsl XL ; multiply divisor by 2
rol XH
rol ZL
rol ZH
rol R0
rol rmp
cp ZL,rDiv1 ; compare with divident
cpc ZH,rDiv2
cpc R0,rDiv3
cpc rmp,rDiv4
brcs Divide2
sub ZL,rDiv1
sbc ZH,rDiv2
sbc R0,rDiv3
sbc rmp,rDiv4
sec
rjmp Divide3
Divide2:
clc
Divide3:
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc Divide1
ret
;
; Multiply measured time in rRes4:rRes3:rRes2:rRes1 by 65536 / fq
(MHz)
; rmp:R0 are the upper bytes of the input
; ZH:ZL:rDiv4:rDiv3:rDiv2:rDiv1 is the interim result
; XH:XL is the multiplicator
; result is in rRes4:rRes3:rRes2:rRes1
;
.EQU cMulti = 65536000 / (cFreq/1000)
;
Multiply:
ldi XH,HIGH(cMulti) ; set multiplicator
ldi XL,LOW(cMulti)
clr ZH
clr ZL
clr rDiv4
clr rDiv3
clr rDiv2
clr rDiv1
clr R0
clr rmp
Multiply1:
cpi XL,0
brne Multiply2
cpi XH,0
breq Multiply4
Multiply2:
lsr XH
ror XL
brcc Multiply3
add rDiv1,rRes1
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
adc ZL,R0
adc ZH,rmp
Multiply3:
lsl rRes1
rol rRes2
rol rRes3
rol rRes4
rol R0
rol rmp
rjmp Multiply1
Multiply4:
ldi rmp,128 ; round result
clr R0
add rDiv2,rmp
adc rDiv3,R0
adc rDiv4,R0
adc ZL,R0
adc ZH,R0
mov rRes1,rDiv3 ; move result
mov rRes2,rDiv4
mov rRes3,ZL
mov rRes4,ZH
ret
;
; Display seconds at buffer end
;
DisplSec:
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'u'
st X+,rmp
ldi rmp,'s'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ret
;
; An overflow has occurred during pulse width calculation
;
PulseOvflw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
st X+,rmp
.IF cDisplay8
ldi ZH,HIGH(2*TxtPOvflw8)
ldi ZL,LOW(2*TxtPOvflw8)
ldi rmp,7
.ELSE
ldi ZH,HIGH(2*TxtPOvflw16)
ldi ZL,LOW(2*TxtPOvflw16)
ldi rmp,15
.ENDIF
PulseOvflw1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne PulseOvflw1
ret
.IF cDisplay8
TxtPOvflw8:
.DB ":error! "
.ELSE
TxtPOvflw16:
.DB ":error calcul.! "
.ENDIF
;
; ======================================================
; Pulse width calculations
; ======================================================
;
; Calculate the pulse width ratio
; active cycle time is in rDelH:rDelL:R0:rmp
; total cycle time is in rDiv
; result will be in rRes
; overflow: carry flag is set
;
CalcPwO: ; overflow
sec
ret
CalcPw:
mov rRes1,rmp ; copy active cycle time to rRes
mov rRes2,R0
mov rRes3,rDelL
mov rRes4,rDelH
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 4
rol rRes2
rol rRes3

http://www.avr-asm-tutorial.net/avr_en/fcount/fcount_m8_v3.html (1 of 4)1/20/2009 7:58:29 PM


40 MHz-Frequency counter with an ATmega8, source code

rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
mov XL,rRes1 ; copy to Z:X
mov XH,rRes2
mov ZL,rRes3
mov ZH,rRes4
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO
add rRes1,XL ; * 24
adc rRes2,XH
adc rRes3,ZL
adc rRes4,ZH
clr ZH ; clear the four MSBs of divisor
clr ZL
clr XH
mov XL,rDelH ; * 256
mov rDelH,rDelL
mov rDelL,R0
mov R0,rmp
clr rmp
lsl R0 ; * 512
rol rDelL
rol rDelH
rol XL
rol XH
lsl R0 ; * 1024
rol rDelL
rol rDelH
rol XL
rol XH
sub rmp,rRes1 ; * 1000
sbc R0,rRes2
sbc rDelL,rRes3
sbc rDelH,rRes4
sbc XL,ZH
sbc XH,ZH
cp XL,rDiv1 ; overflow?
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcc CalcPwO
clr rRes1 ; clear result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
CalcPw1: ; dividing loop
lsl rmp ; multiply by 2
rol R0
rol rDelL
rol rDelH
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1 ; compare with divisor
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw2 ; smaller, roll zero in
sub XL,rDiv1 ; subtract divisor
sbc XH,rDiv2
sbc ZL,rDiv3
sbc ZH,rDiv4
sec ; roll one in
rjmp CalcPw3
CalcPw2:
clc
CalcPw3: ; roll result
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc CalcPw1 ; roll on
lsl rDelL ; round result
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw4
ldi rmp,1 ; round up
add rRes1,rmp
ldi rmp,0
adc rRes2,rmp
adc rRes3,rmp
adc rRes4,rmp
CalcPw4:
tst rRes4 ; check > 1000
brne CalcPwE
tst rRes3
brne CalcPwE
ldi rmp,LOW(1001)
cp rRes1,rmp
ldi rmp,HIGH(1001)
cpc rRes2,rmp
brcc CalcPwE
clc ; no error
ret
CalcPwE: ; error
sec
ret
;
; Display the binary in R2:R1 in the form " 100,0%"
;
DisplPw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
ldi rmp,' '
st X+,rmp
st X+,rmp
clr R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecX2
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall DisplDecX2
ldi ZL,10
inc R0
rcall DisplDecX2
ldi rmp,cDecSep
st X+,rmp
ldi rmp,'0'
add rmp,rRes1
st X+,rmp
ldi rmp,'%'
st X+,rmp
.IF ! cDisplay8
ldi rmp,8
ldi ZL,' '
DisplPw1:
st X+,ZL
dec rmp
brne DisplPw1
.ENDIF
ret
;
; If the first characters in the result buffer are empty,
; place the character in ZL here and add equal, if possible
;
DisplMode:
ldi XH,HIGH(sResult+1) ; point to result buffer
ldi XL,LOW(sResult+1)
ld rmp,X ; read second char
cpi rmp,' '
brne DisplMode1
ldi rmp,'='
st X,rmp
DisplMode1:
sbiw XL,1
ld rmp,X ; read first char
cpi rmp,' '
brne DisplMode2
st X,ZL
DisplMode2:
ret
;
;=================================================
; Display binary numbers as decimal
;=================================================
;
; Converts a binary in R2:R1 to a digit in X
; binary in Z
;
DecConv:
clr rmp
DecConv1:
cp R1,ZL ; smaller than binary digit?
cpc R2,ZH
brcs DecConv2 ; ended subtraction
sub R1,ZL
sbc R2,ZH
inc rmp
rjmp DecConv1
DecConv2:
tst rmp
brne DecConv3
tst R0
brne DecConv3
ldi rmp,' ' ; suppress leading zero
rjmp DecConv4
DecConv3:
subi rmp,-'0'
DecConv4:
st X+,rmp
ret
;
; Display fractional number in R3:R2:(Fract)R1
;
DisplFrac:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
.ENDIF
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DisplDecY2
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecY2
.IF ! cDisplay8
ldi rmp,c1kSep
tst R0
brne DisplFrac0
ldi rmp,' '
DisplFrac0:
st X+,rmp
.ENDIF
ldi ZL,100
rcall DisplDecY1
ldi ZL,10
rcall DisplDecY1
ldi rmp,'0'
add rmp,R2
st X+,rmp
tst R1 ; fraction = 0?
brne DisplFrac1
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
st X+,rmp
st X+,rmp
.ENDIF
ret
DisplFrac1:
ldi rmp,cDecSep
st X+,rmp
.IF cDisplay8
ldi ZL,2
.ELSE
ldi ZL,3
.ENDIF
DisplFrac2:
clr rRes3
clr rRes2
mov R0,rRes1 ; * 1
lsl rRes1 ; * 2
adc rRes2,rRes3
lsl rRes1 ; * 4
rol rRes2
add rRes1,R0 ; * 5
adc rRes2,rRes3
lsl rRes1 ; * 10
rol rRes2
ldi rmp,'0'
add rmp,rRes2
st X+,rmp
dec ZL
brne DisplFrac2
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X+,rmp
.ENDIF
ret
;
; Convert a decimal in R4:R3:R2, decimal in ZH:ZL
;
DisplDecY2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY2a:
cp rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecY2b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecY2a
DisplDecY2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY2c
ldi rmp,' '
DisplDecY2c:
st X+,rmp
ret
;
; Convert a decimal decimal in R:R2, decimal in ZL
;
DisplDecY1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY1a:
cp rRes2,ZL
cpc rRes3,rDiv2
brcs DisplDecY1b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecY1a
DisplDecY1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY1c
ldi rmp,' '
DisplDecY1c:
st X+,rmp
ret
;
; Display a 4-byte-binary in decimal format on result line 1
; 8-bit-display: "12345678"
; 16-bit-display: " 12.345.678 Hz "
;
Displ4Dec:
ldi rmp,BYTE1(100000000) ; check overflow
cp rRes1,rmp
ldi rmp,BYTE2(100000000)
cpc rRes2,rmp
ldi rmp,BYTE3(100000000)
cpc rRes3,rmp
ldi rmp,BYTE4(100000000)
cpc rRes4,rmp
brcs Displ4Dec1
rjmp CycleOvf
Displ4Dec1:
clr R0 ; suppress leading zeroes
ldi XH,HIGH(sResult) ; X to result buffer
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' ' ; clear the first two digits
st X+,rmp
st X+,rmp
.ENDIF
ldi ZH,BYTE3(10000000) ; 10 mio
ldi ZL,BYTE2(10000000)
ldi rmp,BYTE1(10000000)
rcall DisplDecX3
ldi ZH,BYTE3(1000000) ; 1 mio
ldi ZL,BYTE2(1000000)
ldi rmp,BYTE1(1000000)
rcall DisplDecX3
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec2
ldi rmp,' '
Displ4Dec2:
st X+,rmp
.ENDIF
ldi ZH,BYTE3(100000) ; 100 k
ldi ZL,BYTE2(100000)
ldi rmp,BYTE1(100000)
rcall DisplDecX3
ldi ZH,HIGH(10000) ; 10 k
ldi ZL,LOW(10000)
rcall DisplDecX2
ldi ZH,HIGH(1000) ; 1 k
ldi ZL,LOW(1000)
rcall DisplDecX2
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec3
ldi rmp,' '
Displ4Dec3:
st X+,rmp
.ENDIF
ldi ZL,100 ; 100
rcall DisplDecX1
ldi ZL,10
rcall DisplDecX1
ldi rmp,'0' ; 1
add rmp,R1
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL:rmp
;
DisplDecX3:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; subtractor for byte 4
DisplDecX3a:
cp rRes1,rmp ; compare
cpc rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecX3b ; ended
sub rRes1,rmp ; subtract
sbc rRes2,ZL
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecX3a
DisplDecX3b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX3c
ldi rmp,' '
DisplDecX3c:
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL
;
DisplDecX2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX2a:
cp rRes1,ZL
cpc rRes2,ZH
cpc rRes3,rDiv2
brcs DisplDecX2b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,ZH
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecX2a
DisplDecX2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX2c
ldi rmp,' '
DisplDecX2c:
st X+,rmp
ret
;
; Convert a decimal in R2:R1, decimal in ZL
;
DisplDecX1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX1a:
cp rRes1,ZL
cpc rRes2,rDiv2
brcs DisplDecX1b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,rDiv2
inc rDiv1
rjmp DisplDecX1a
DisplDecX1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX1c
ldi rmp,' '
DisplDecX1c:
st X+,rmp
ret
;
;=================================================
; Delay routines
;=================================================
;
Delay10ms:
ldi rDelH,HIGH(10000)
ldi rDelL,LOW(10000)
rjmp DelayZ
Delay15ms:
ldi rDelH,HIGH(15000)
ldi rDelL,LOW(15000)
rjmp DelayZ
Delay4_1ms:
ldi rDelH,HIGH(4100)
ldi rDelL,LOW(4100)
rjmp DelayZ
Delay1_64ms:
ldi rDelH,HIGH(1640)
ldi rDelL,LOW(1640)
rjmp DelayZ
Delay100us:
clr rDelH
ldi rDelL,100
rjmp DelayZ
Delay40us:
clr rDelH
ldi rDelL,40
rjmp DelayZ
;
; Delays execution for Z microseconds
;
DelayZ:
.IF cFreq>18000000
nop
nop
.ENDIF
.IF cFreq>16000000
nop
nop
.ENDIF
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
sbiw rDelL,1 ; 2
brne DelayZ ; 2
ret
;
; =========================================
; Main Program Start
; =========================================
;
main:
ldi rmp,HIGH(RAMEND) ; set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
clr rFlg ; set flags to default
;
.IF debug
.EQU number = 100000000
ldi rmp,BYTE4(number)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(number)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(number)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(number)
mov rRes1,rmp
mov rDiv1,rmp
rcall CycleM6
beloop: rjmp beloop
.ENDIF
.IF debugpulse
.EQU nhigh = 100000000
.EQU nlow = 15000
ldi rmp,BYTE4(nhigh)
sts sCtr+3,rmp
ldi rmp,BYTE3(nhigh)
sts sCtr+2,rmp
ldi rmp,BYTE2(nhigh)
sts sCtr+1,rmp
ldi rmp,BYTE1(nhigh)
sts sCtr,rmp
ldi rmp,BYTE4(nlow)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(nlow)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(nlow)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(nlow)
mov rRes1,rmp
mov rDiv1,rmp
sbr rFlg,1<<bEdge
rcall CycleM7
bploop: rjmp bploop
.ENDIF
;
; Clear the output storage
;
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,' '
mov R0,rmp
ldi rmp,32
main1:
st Z+,R0
dec rmp
brne main1
;
; Init the Uart
;
.IF cUart
rcall UartInit
ldi rmp,1<<bUMonU ; monitor U over Uart
sts sUartFlag,rmp
ldi rmp,20 ; 5 seconds
sts sUartMonURpt,rmp ; set repeat default value
ldi rmp,1
sts sUartMonUCnt,rmp
ldi rmp,4 ; 1 seconds
sts sUartMonFCnt,rmp
.ENDIF
;
; Init the LCD
;
.IF cDisplay
rcall LcdInit
.ENDIF
;
; Disable the Analog comparator
;
ldi rmp,1<<ACD
out ACSR,rmp
;
; Disable the external prescaler by 16
;
sbi pPrescD,bPresc ; set prescaler port bit to output
sbi pPresc,bPresc ; disable the prescaler
;
; Init the ADC
;
ldi rmp,(1<<REFS1)|(1<<REFS0) ; int.ref, channel 0
out ADMUX,rmp
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; prescaler = 128
out ADCSRA,rmp
;
; Start main interval timer
;
ldi rmp,cCmp2 ; set Compare Match
out OCR2,rmp
ldi rmp,cPre2|(1<<WGM21) ; CTC mode and prescaler
out TCCR2,rmp
;
; Start timer/counter TC2 interrupts
;
ldi rmp,(1<<OCIE2) ; Interrupt mask
out TIMSK,rmp
;
; Set initial mode to mode 1
;
ldi rmp,1 ; initial mode = 1
sts sModeNext,rmp
rcall SetModeNext
;
sei ; enable interrupts
;
loop:
sleep ; send CPU to sleep
nop
sbrc rFlg,bCyc ; check cycle end
rcall Cycle
sbrc rFlg,bAdc
rcall Interval
.IF cUart
sbrc rFlg,bUartRxLine ; check line complete
rcall UartRxLine ; call line complete
.ENDIF
rjmp loop ; go to sleep
;
; Timer interval for calculation and display
;
Interval:
cbr rFlg,1<<bAdc ; clear flag
lds ZL,sAdc1L ; read ADC channel 1 value
lds ZH,sAdc1H
mov XL,ZL ; copy to X
mov XH,ZH
lsl ZL ; multiply by 2
rol ZH
lsl ZL ; multiply by 4
rol ZH
add ZL,XL ; multiply by 5
adc ZH,XH
lsr ZH ; multiply by 2.5
ror ZL
cpi ZH,10 ; larger than 9?
brcs Interval1
ldi ZH,9 ; set to 9
Interval1:
sts sModeNext,ZH ; store next mode
cp rMode,ZH ; new mode?
breq Interval2 ; continue current mode
rcall SetModeNext ; start new mode
Interval2:
.IF cUart || cDisplay
lds R0,sAdc0L ; read ADC value
lds R1,sAdc0H
rcall cAdc2U ; convert to text
.IF cDisplay
rcall LcdDisplayFT
rcall LcdDisplayU
.ENDIF
.IF cUart
rcall UartMonU
.ENDIF
.ENDIF
ret
;
; Frequency/Time measuring cycle ended, calculate results
;
Cycle:
sbrc rFlg,bOvf ; check overflow
rjmp CycleOvf ; jump to overflow
mov rRes1,rCpy1 ; copy counter
mov rRes2,rCpy2
mov rRes3,rCpy3
mov rRes4,rCpy4
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
mov rDiv1,rRes1 ; copy again
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
.IF cUart
ldi ZH,HIGH(UartMonF) ; put monitoring frequency on stack
ldi ZL,LOW(UartMonF)
push ZL
push ZH
.ENDIF
ldi ZH,HIGH(CycleTab) ; point to mode table
ldi ZL,LOW(CycleTab)
add ZL,rMode ; displace table by mode
brcc Cycle1
inc ZH
Cycle1:
ijmp ; call the calculation routine
; overflow occurred
CycleOvf:
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
ldi XH,HIGH(sResult) ; point to result buffer
ldi XL,LOW(sResult)
.IF cDisplay8
ldi ZH,HIGH(2*TxtOvf8) ; point to short message
ldi ZL,LOW(2*TxtOvf8)
ldi rmp,8
.ELSE
ldi ZH,HIGH(2*TxtOvf16) ; point to long message
ldi ZL,LOW(2*TxtOvf16)
ldi rmp,16
.ENDIF
CycleOvf1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne CycleOvf1
ret
;
.IF cDisplay8
TxtOvf8:
.DB " ovflow"
.ELSE
TxtOvf16:
.DB " overflow "
.ENDIF
; Table with routines for the 8 modes
CycleTab:
rjmp CycleM0
rjmp CycleM1
rjmp CycleM2
rjmp CycleM3
rjmp CycleM4
rjmp CycleM5
rjmp CycleM6
rjmp CycleM7
rjmp CycleM8
ret ; voltage only
;
; Mode 0: Measured prescaled frequency, display frequency
;
CycleM0:
clr R5 ; for detecting an overflow in R5
lsl R1 ; * 2
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 4
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 8
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 16
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 32
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 64
rol R2
rol R3
rol R4
rol R5
tst R5 ; check overflow
breq CycleM0a ; no error
rjmp CycleOvf
CycleM0a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'F'
rjmp DisplMode
;
; Mode 1: Frequency measured, prescale = 1, display frequency
;
CycleM1:
clr rDiv1 ; detect overflow in rDiv1
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4

http://www.avr-asm-tutorial.net/avr_en/fcount/fcount_m8_v3.html (2 of 4)1/20/2009 7:58:29 PM


40 MHz-Frequency counter with an ATmega8, source code

rol rDiv1
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
tst rDiv1 ; check overflow
breq CycleM1a ; no error
rjmp CycleOvf
CycleM1a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'f'
rjmp DisplMode
;
; Mode 2: Time measured, prescale = 1, display frequency
;
CycleM2:
rcall Divide
tst rRes4
brne CycleM2a
rcall DisplFrac
ldi ZL,'v'
rcall DisplMode
ret
CycleM2a:
mov rRes1,rRes2 ; number too big, skip fraction
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'v'
rcall DisplMode
ret
;
; Measure time, display rounds per minute
;
CycleM3:
rcall Divide
clr R0 ; overflow detection
clr rmp
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
mov rDiv1,rRes1 ; copy
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 32
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 64
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
tst R0 ; overflow?
breq CycleM3a
rjmp CycleOvf
CycleM3a:
sub rRes1,rDiv1
sbc rRes2,rDiv2
sbc rRes3,rDiv3
sbc rRes4,rDiv4
mov rRes1,rRes2
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'r'
st X+,rmp
ldi rmp,'p'
st X+,rmp
ldi rmp,'m'
st X+,rmp
.ENDIF
ldi ZL,'u'
rcall DisplMode
ret
;
; Measure time high+low, display time
;
CycleM4:
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'t'
rcall DisplMode
ret
;
; Measure time high, display time
;
CycleM5:
sbrs rFlg,bEdge
rjmp CycleM5a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'h'
rcall DisplMode
CycleM5a:
ret
;
; Measure time low, display time
;
CycleM6:
sbrc rFlg,bEdge
rjmp CycleM6a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'l'
rcall DisplMode
CycleM6a:
ret
;
; Measure time high and low, display pulse width ratio high in %
; if the edge was negative, store the measured time, if positive
calculate
; rRes and rDiv hold the active low time, sCtr the last active
high time
; to CalcPw: rDelH:rDelL:R0:rmp = active high time
;
CycleM7:
sbrs rFlg,bEdge
rjmp CycleM7a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rRes1,Z+ ; copy counter value
ld rRes2,Z+
ld rRes3,Z+
ld rRes4,Z+
add rDiv1,rRes1 ; add to total time
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
brcs CycleM7b
mov rmp,rRes1 ; copy high value to divisor
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM7b ; error
rcall DisplPw ; display the ratio
ldi ZL,'P'
rjmp DisplMode
CycleM7a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM7b: ; overflow
ldi rmp,'P'
rjmp PulseOvFlw
;
; Measure time high and low, display pulse width ratio low in %
; if the edge was negative, store the measured time, if positive
calculate
; rRes and rDiv hold the active low time, sCtr the last active
high time
; to CalcPw: rDelH:rDelL:R0:rmp = active low time
;
CycleM8:
sbrs rFlg,bEdge
rjmp CycleM8a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rmp,Z+ ; read high-time
ld R0,Z+
ld rDelL,Z+
ld rDelH,Z
add rDiv1,rmp ; add to total time
adc rDiv2,R0
adc rDiv3,rDelL
adc rDiv4,rDelH
mov rmp,rRes1 ; copy the active low time
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM8b ; error
rcall DisplPw ; display the ratio
ldi ZL,'p'
rjmp DisplMode
CycleM8a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM8b: ; overflow
ldi rmp,'p'
rjmp PulseOvFlw
;
; Converts an ADC value in R1:R0 to a voltage for display
; cAdc2U input: ADC value, output: Voltage in V for display
;
cAdc2U:
clr R2 ; clear the registers for left shift in R3:R2
clr R3
ldi rmp,HIGH(cMultiplier) ; Multiplier to R5:R4
mov R5,rmp
ldi rmp,LOW(cMultiplier)
mov R4,rmp
clr XL ; clear result in ZH:ZL:XH:XL
clr XH
clr ZL
clr ZH
cAdc2U1:
lsr R5 ; shift Multiplier right
ror R4
brcc cAdc2U2 ; bit is zero, don't add
add XL,R0 ; add to result
adc XH,R1
adc ZL,R2
adc ZH,R3
cAdc2U2:
mov rmp,R4 ; check zero
or rmp,R5
breq cAdc2U3 ; end of multiplication
lsl R0 ; multiply by 2
rol R1
rol R2
rol R3
rjmp cAdc2U1 ; go on multipying
cAdc2U3:
ldi rmp,$80 ; round up
add XL,rmp
ldi rmp,$00
adc XH,rmp
adc ZL,rmp
adc ZH,rmp
tst ZH ; check overflow
mov R1,XH ; copy result to R2:R1
mov R2,ZL
ldi XH,HIGH(sResult+16) ; point to result
ldi XL,LOW(sResult+16)
ldi rmp,'U'
st X+,rmp
breq cAdc2U5
ldi ZH,HIGH(2*AdcErrTxt)
ldi ZL,LOW(2*AdcErrTxt)
cAdc2U4:
lpm
tst R0
breq cAdc2U6
sbiw ZL,1
st X+,R0
rjmp cAdc2U4
cAdc2U5:
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DecConv
inc R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DecConv
ldi rmp,cDecSep
st X+,rmp
clr ZH
ldi ZL,100
rcall DecConv
ldi ZL,10
rcall DecConv
ldi rmp,'0'
add rmp,R1
st X+,rmp
ldi rmp,'V'
st X,rmp
lds rmp,sResult+17
cpi rmp,' '
brne cAdc2U6
ldi rmp,'='
sts sResult+17,rmp
cAdc2U6:
ret
;
AdcErrTxt:
.DB "overflw",$00
;
; ===========================================
; Lcd display routines
; ===========================================
;
.IF cDisplay ; if display connected
;
; LcdE pulses the E output for at least 1 us
;
LcdE:
sbi PORTB,bLcdE
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
.IF cFreq>2000000
nop
nop
.ENDIF
nop
nop
cbi PORTB,bLcdE
ret
;
; outputs the content of rmp (temporary
; 8-Bit-Interface during startup)
;
LcdRs8:
out PORTB,rmp
rcall LcdE
ret
;
; write rmp as 4-bit-command to the LCD
;
LcdRs4:
mov R0,rmp ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original back
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE
mov rmp,R0 ; restore rmp
ret
;
; write rmp as data over 4-bit-interface to the LCD
;
LcdData4:
push rmp ; save rmp
mov rmp,R0 ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original again
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE
rcall Delay40us
pop rmp ; restore rmp
ret
;
; writes the text in flash to the LCD, number of
; characters in rmp
;
LcdText:
lpm ; read character from flash
adiw ZL,1
rcall LcdData4 ; write to
rcall delay40us
dec rmp
brne LcdText
ret
;
; Inits the LCD with a 4-bit-interface
;
LcdInit:
ldi rmp,0x0F | (1<<bLcdE) | (1<<bLcdRs)
out DDRB,rmp
clr rmp
out PORTB,rmp
rcall delay15ms ; wait for complete self-init
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay4_1ms ; wait for 4.1 ms
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay100us ; wait for 100 us
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay40us ; delay 40 us
ldi rmp,0x02 ; Function set 4-bit-interface
rcall LcdRs8
rcall delay40us
.IF cDisplay2
ldi rmp,0x28 ; 4-bit-interface, two line display
.ELSE
ldi rmp,0x20 ; 4-bit-interface, single line display
.ENDIF
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x08 ; display off
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x01 ; display clear
rcall LcdRs4
rcall delay1_64ms ; delay 1.64 ms
ldi rmp,0x06 ; increment, don't shift
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x0C ; display on
rcall LcdRs4
rcall delay40us
ldi rmp,0x80 ; position on line 1
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
ldi ZH,HIGH(2*LcdInitTxt8)
ldi ZL,LOW(2*LcdInitTxt8)
.ELSE
ldi rmp,16
ldi ZH,HIGH(2*LcdInitTxt16)
ldi ZL,LOW(2*LcdInitTxt16)
.ENDIF
rcall LcdText
.IF cDisplay2
ldi rmp,0xC0 ; line 2
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
.ELSE
ldi XH,HIGH(sResult+25)
ldi XL,LOW(sResult+25)
ldi ZH,HIGH(2*LcdInitTxtMode)
ldi ZL,LOW(2*LcdInitTxtMode)
ldi rmp,6
LcdInitMode:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne LcdInitMode
ldi rmp,16
.ENDIF
rcall LcdText
.ENDIF
ret
.IF cDisplay8
LcdInitTxt8:
.DB "F-CNT V1"
.IF cDisplay2
.DB "-DG4FAC-"
.ENDIF
.ELSE
LcdInitTxt16:
.DB "Freq-counter V01"
.IF cDisplay2
.DB " (C)2005 DG4FAC "
LcdInitTxtMode:
.DB " Mode="
.ENDIF
.ENDIF
;
; Display frequency/time on Lcd
;
LcdDisplayFT:
.IF ! cDisplay2 ; single line display
cpi rMode,cModeVoltage ; voltage display selected?
breq LcdDisplayFT2
.ENDIF
ldi rmp,$80 ; set display position to line 1
rcall LcdRs4
rcall Delay40us
ldi ZH,HIGH(sResult) ; point Z to line buffer
ldi ZL,LOW(sResult)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayFT1:
ld R0,Z+ ; read a char
rcall LcdData4 ; display on LCD
dec rmp
brne LcdDisplayFT1
LcdDisplayFT2:
ret
;
; Display voltage on the display
;
LcdDisplayU:
.IF cDisplay2 ; two-line LCD connected
.IF !cDisplay8
lds rmp,sModeNext
subi rmp,-'0'
sts sResult+31,rmp
.ENDIF
ldi rmp,$C0 ; output to line 2
.ELSE
cpi rMode,cModeVoltage ; check switch
brne LcdDisplayU2
ldi rmp,$80 ; output to line 1
.ENDIF
rcall LcdRs4 ; set output position
rcall Delay40us
ldi ZH,HIGH(sResult+16) ; point to result
ldi ZL,LOW(sResult+16)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayU1:
ld R0,Z+ ; read character
rcall LcdData4
dec rmp ; next char
brne LcdDisplayU1 ; continue with chars
LcdDisplayU2:
ret
;
.ENDIF ; end LCD routines to be included
;
; ===========================================
; Uart routines
; ===========================================
;
.IF cUart
UartInit: ; Init the Uart on startup
.EQU cUbrr = (cFreq/cBaud/16)-1 ; calculating UBRR single speed
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi rmp,HIGH(cUbrr) ; set URSEL to zero, set baudrate msb
out UBRRH,rmp
ldi rmp,LOW(cUbrr) ; set baudrate lsb
out UBRRL,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; set 8 bit
characters
out UCSRC,rmp
ldi rmp,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable RX/TX and
RX-Ints
out UCSRB,rmp
rcall delay10ms ; delay for 10 ms duration
ldi ZH,HIGH(2*txtUartInit)
ldi ZL,LOW(2*txtUartInit)
rjmp UartSendTxt
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
; .EQU UartRxbLen = 38 ; Buffer length in bytes
; sUartFlag: ; flag register for Uart
; .BYTE 1
; .EQU bUMonU = 0 ; displays voltage over Uart
; .EQU bUMonF = 1 ; displays frequency over Uart
; ; free: bits 2..7
; sUartMonUCnt: ; counter for Monitoring voltage
; .BYTE 1
; sUartMonURpt: ; counter preset for monitoring voltage
; .BYTE 1
; sUartRxBp: ; buffer pointer
; .BYTE 1
; sUartRxBs: ; buffer
; .BYTE UartRxbLen
; sUartRxBe: ; buffer end
; .EQU cNul = $00
; .EQU cClrScr = $0C
; .EQU cCr = $0D
; .EQU cLf = $0A
;
UartRxLine:
cbr rFlg,1<<bUartRxLine ; clear line complete flag
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi ZH,HIGH(UartReturn) ; push return adress to stack
ldi ZL,LOW(UartReturn)
push ZL
push ZH
ldi ZH,HIGH(sUartRxBs) ; set Z to Buffer-Start
ldi ZL,LOW(sUartRxBs)
ld rmp,Z+ ; read first character
cpi rmp,'h' ; help?
brne UartRxLine1
rjmp UartHelp
UartRxLine1:
cpi rmp,'?' ; help?
brne UartRxLine2
rjmp UartHelp
UartRxLine2:
cpi rmp,'U' ; monitor U on
brne UartRxLine3
rcall UartGetPar
sec
rjmp UartMonUSetC
UartRxLine3:
cpi rmp,'u' ; monitor U off
brne UartRxLine4
clc
rjmp UartMonUSetC
UartRxLine4:
cpi rmp,'F' ; monitor F on
brne UartRxLine5
rcall UartGetPar
sec
rjmp UartMonFSetC
UartRxLine5:
cpi rmp,'f' ; monitor f off
brne UartRxLine6
clc
rjmp UartMonFSetC
UartRxLine6:
cpi rmp,'p' ; parameter?
brne UartRxLine7
rjmp UartMonPar
UartRxLine7:
ldi ZH,HIGH(2*txtUartUnknown) ; send unknown command
ldi ZL,LOW(2*txtUartUnknown)
ret
UartHelp:
ldi ZH,HIGH(2*txtUartHelp) ; send help text
ldi ZL,LOW(2*txtUartHelp)
ret
UartMonUSetC:
lds rmp,sUartFlag
brcs UartMonUSetC1
cbr rmp,1<<bUMonU ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOff)
ldi ZL,LOW(2*txtUartUOff)
ret
UartMonUSetC1:
brne UartMonUSetC2
sts sUartMonURpt,R0
sts sUartMonUCnt,R0
UartMonUSetC2:
sbr rmp,1<<bUMonU ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOn)
ldi ZL,LOW(2*txtUartUOn)
ret
UartMonFSetC:
lds rmp,sUartFlag
brcs UartMonFSetC1
cbr rmp,1<<bUMonF ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOff)
ldi ZL,LOW(2*txtUartFOff)
ret
UartMonFSetC1:
brne UartMonFSetC2
sts sUartMonFRpt,R0
sts sUartMonFCnt,R0
UartMonFSetC2:
sbr rmp,1<<bUMonF ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOn)
ldi ZL,LOW(2*txtUartFOn)
ret
UartMonPar:
ldi ZH,HIGH(2*txtUartNul)
ldi ZL,LOW(2*txtUartNul);
ldi rmp,'U'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonURpt
rcall UartHexR
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'F'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonFRpt
rjmp UartHexR
;
; Get Parameter from line
;
UartGetPar:
clr R0 ; result register
ld rmp,Z+ ; read char
cpi rmp,cCr ; carriage return
breq UartGetParNoPar
cpi rmp,cLf ; line feed
breq UartGetParNoPar
cpi rmp,'=' ;
brne UartGetParErr
UartGetPar1:
ld rmp,Z+ ; read next char
cpi rmp,cCr ; carriage return?
breq UartGetPar2
cpi rmp,cLf ; line feed?
breq UartGetPar2
subi rmp,'0' ; subtract 0
brcs UartGetParErr
cpi rmp,10 ; larger than 9?
brcc UartGetParErr
mov rir,R0 ; copy to rir
lsl R0 ; * 2
brcs UartGetParErr
lsl R0 ; * 4
brcs UartGetParErr
add R0,rir ; * 5
brcs UartGetParErr
lsl R0 ; * 10
brcs UartGetParErr
add R0,rmp ; add new decimal
brcs UartGetParErr
rjmp UartGetPar1
UartGetPar2:
sez
ret
UartGetParErr:
ldi ZH,HIGH(2*txtUartErr)
ldi ZL,LOW(2*txtUartErr)
rcall UartSendTxt
UartGetParNoPar:
clz ; No parameter set
ret
;
; Hex output over Uart, for debugging
;
UartHexR:
push rmp
swap rmp
rcall UartHexN
pop rmp
UartHexN:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs UartHexN1
subi rmp,-7
UartHexN1:
rjmp UartSendChar
ret
;
; Return from Uart-Routines, displays text in Z
;
UartReturn:
rcall UartSendTxt ; send text in Z
ldi ZH,HIGH(2*txtUartCursor)
ldi ZL,LOW(2*txtUartCursor)
rjmp UartSendTxt
;
; Send character in rmp over Uart
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartSendChar
out UDR,rmp
ret
;
; Monitoring the voltage over the Uart
;
UartMonU:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonU ; displays voltage over Uart
ret
lds rmp,sUartMonUCnt ; read counter
dec rmp
sts sUartMonUCnt,rmp
brne UartMonU2
lds rmp,sUartMonURpt
sts sUartMonUCnt,rmp
ldi ZH,HIGH(sResult+16)
ldi ZL,LOW(sResult+16)
ldi rmp,8
UartMonU1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonU1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonU1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonU2:
ret
;
; Monitor frequency over UART
;
UartMonF:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonF ; displays frequency over Uart
ret
lds rmp,sUartMonFCnt ; read counter
dec rmp
sts sUartMonFCnt,rmp
brne UartMonF2
lds rmp,sUartMonFRpt
sts sUartMonFCnt,rmp
ldi ZH,HIGH(sResult)

http://www.avr-asm-tutorial.net/avr_en/fcount/fcount_m8_v3.html (3 of 4)1/20/2009 7:58:29 PM


40 MHz-Frequency counter with an ATmega8, source code

ldi ZL,LOW(sResult)
ldi rmp,16
UartMonF1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonF1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonF1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonF2:
ret
;
; Send text from flash to UART, null byte ends transmit
;
UartSendTxt:
lpm ; read character from flash
adiw ZL,1
tst R0 ; check end of text
breq UartSendTxtRet
UartSendTxtWait:
sbis UCSRA,UDRE ; wait for empty char
rjmp UartSendTxtWait
out UDR,R0 ; send char
rjmp UartSendTxt
UartSendTxtRet:
ret
;
; Uart text constants
;
txtUartInit:
.DB " ",cClrScr
.DB "************************************************* ",cCr,cLf
.DB "* Frequency- and voltmeter (C)2005 by g.schmidt * ",cCr,cLf
.DB "************************************************* ",cCr,cLf
txtUartMenue:
.DB cCr,cLf,"Commands: <h>elp",cCr,cLf
txtUartCursor:
.DB cCr,cLf,"i> ",cNul
txtUartUnknown:
.DB cCr,cLf,"Unknown command!",cNul,cNul
txtUartUOff:
.DB "Voltage monitoring is off.",cNul,cNul
txtUartUOn:
.DB "Voltage monitoring is on. ",cNul,cNul
txtUartFOff:
.DB "Frequency monitoring is off.",cNul,cNul
txtUartFOn:
.DB "Frequency monitoring is on. ",cNul,cNul
txtUartErr:
.DB "Error in parameter! ",cNul,cNul
txtUartHelp:
.DB cCr,cLf,"Help: ",cCr,cLf
.DB "U[=N](on) or u(Off): monitor voltage output, N=1..255,",cCr,cLf
.DB "F[=N](On) or f(Off): monitor frequency output N=1..255, ",cCr,
cLf
.DB "p: display monitoring parameters, ",cCr,cLf
.DB "h or ?: this text."
txtUartNul:
.DB cNul,cNul
.ENDIF
;
; End of source code
;

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/fcount/fcount_m8_v3.html (4 of 4)1/20/2009 7:58:29 PM


40MHz-Frequency counter with ATmega8

Pfad: Home => AVR-Overview => Applications => Frequency counter

40MHz-Frequency counter with ATmega8


This application of an AVR describes a frequency counter with ATMEL's ATmega8 with the following properties:

● Digital- and Analog-input, voltage measuring input


● Input stage with preamp and prescaler by 16
● Display with a single- ode double-line LCD
● Nine measuring- and display modes, adjustable with a potentiometer:
❍ 0: Frequency measurement with prescaler, gate time 0,25 s, result in Hz

❍ 1: Frequency measurement without prescaler, gate time 0,25 s, result in Hz

❍ 2: Frequency measurement as period measurement with conversion, result in 0,01 Hz bzw. 0,001 Hz

❍ 3: Rounds per Minute, without prescaler, via period measurement and conversion, result in rpm

❍ 4: Period duration complete cycle, result in microseconds

❍ 5: Period duration high-period, result in microseconds

❍ 6: Period duration low-period, result in microseconds

❍ 7: Period portion high-period, result in 0,1%

❍ 8: Period portion low-period, result in 0,1%

❍ 9: Voltage measurement, result in 0,001 Volt

● The selection of mode 9 (potentiometer on the right) swiches frequency/time/period measurements off.
● SIO-Interface for connecting to a PC
● Xtal oscillator 16 MHz

0. Content
● 1. Hardware
❍ 1.1 Input unit

❍ 1.2 Processor unit

❍ 1.3 LCD unit

❍ 1.4 SIO-Interface

❍ 1.5 Hints for mounting

● 2. Operation
❍ 2.1 Potentiometer for mode selection

❍ 2.2 Voltage measurement

● 3. Software
❍ 3.1 Adjustments prior to assembling

❍ 3.2 Fuses

❍ 3.3 Commented source code

1 Hardware
The frequency counter consists of an input unit (preamp and prescaler) and the processor unit.

1.1 Input unit

The input unit has an analogue and a digital input unit.


The signal on the analogue input is amplified by a fast operation amplifier NE592. Its output signal is adjusted to the the input of a NAND 74HCT132.
The digital input is directly fed into the NAND.
Depending from a processor signal the output of the NAND is either transferred directly to the processor's counting port or is divided by 16 by a 74HCT93.

1.2 Processor unit

The processor unit is designed around the ATmega8. The processor is driven with an xtal of 16 MHz on its pins XTAL1 and XTAL2. The ceramic capacitors of 22 pF help to accelerate the oscillator during start-up.
The supply voltage of 5 volts is attached to pin 8 (GND) and 7 (GND) and blocked by a ceramic concensator of 100 nF. Supply of the AD converter is by 5 volt over an inductor of 22 µH to pin 22, also blocked by a 100 nF
condensator. The internal reference voltage is filtered by a film capacitor of 100 nF.
The AD conversion input pin PC1 is attached to the potentiometer that selects the mode. The resistor of 100 k limits its output voltage to 2,5 V. If a certain mode shall be fixed, a trim potentiometer or a voltage divider with two
resistors can be used.
On the AD converter channel ADC0 (on PC0) is attached to a voltage divider for the input signal to measure input voltages. In the default case, a maximum of 5.12 V can be measured. By changing the voltage divider resistors,
range and resolution can be easily changed. The input of the ADC is blocked against high frequency influence.
The signals TXD and RXD make up the serial interface and attached to the driver IC MAX232. The electrolytic condensators on the MAX232 provide the necessary voltages for the serial RS232 interface. The serial signals are
attached to a 10-pole connector that delivers a 9-pole standard serial connector. The signals CTS, DSR and CD are activated by resistors of 2k2 to the supply voltage.
The I/O pin PC5 drives the prescaler. If high, the prescaler is disabled, if low the signal is divided by 16.
The signal input from the preamp/prescaler is attached to the input INT0 (for edge detection) as well as to T0 (for counting signals).
The port bits PB0 to PB3 serve the four data bits of the LCD. The Enable-input of the LCD is driven by PB5, its RS input by PB4. The Enable-input is via a 100 k resistor attached to GND to disable the input in case the port bit
is inactive. The V0 input of the LCD is attached to a trim potentiometer of 10 k to adjust the contrast of the LCD.
The port bits MOSI, SCK and MISO as well as the RESET signal are attached to a 10-pole connector, over which the processor can be programmed. The red LED is on if programming is active. Supply voltage lines are also
attached to this connector.
The RESET input is attached with a 10 k resistor to the supply voltage.

1.3 LCD display

The LCD is attached over a standard 14-pole connector to the processor unit. You can use LCDs with 8, 16
or more characters per line and single or double lines (adjustable via software).

1.4 SIO interface

The counter has a SIO connection, so measuring data can be read and parameters can be written.

1.5 Hints for mounting

The complete circuit was build on a breadboard of 10 * 5 cm and wired with enammelled copper.

Two of the srews for the LCD also fix the breadboard.

All components, including the supply and a 9 V battery fit into a small casing.

2. Operation
Operation is very easy. A selection between analogue and digital input is not necessary, just attach the source to the required female connector. Just adjust the trim potentiometer to a setting where signals from the analogue
input are measured, and where no false signals from the opamp confuse these measurements.

2.1 Potentiometer for mode selection

The mode selector (potentiometer) selects the mode. If no input signals are present, and a mode based on signal duration measurement is selected, update of the display is not performed immediately but on the first detected
edge.

The display of results on a two-line-LCD with 16 characters is as follows:

Mode Measured Method Display format


0 Frequency Counting, Prescaler=16 F=99,999,999 Hz
1 Frequency Counting, Prescaler=1 f= 9,999,999 Hz
2 Frequency Period duration v= 9,999.999 Hz
3 Rounds per minute Period duration u= 9,999,999 rpm
4 Period duration Period duration t=99,999,999 us
5 High-period Period duration h=99,999,999 us
6 Low-period Period duration l=99,999,999 us
7 High-period portion Period duration P=100.0%
8 Low-period portion Period duration p=100,0%
9 Voltage AD-Conversion U=9.999V

In a single-line LCD, the voltage is displayed only if mode 9 is selected. At less than 16 character per line, thousand separators and dimension are not displayed. Abbreviations for the measuring code are diplayed only if the
displayed value does not require this space.

2.2 Volatge measurements

The voltage on the input pin is measured and displayed four times per second.

3. Software
The software is completely written in Assembler. Prior to assembling the source code the internal adjustments have to be made (see 3.1). During or after programming the hex code to the chip's flash the fuses have to be
changed (see 3.2). Note that after setting the fuses, the chip is only accessible with an external xtal attached.

3.1 Adjustments prior to assembling

The following adjustments have to be made on the source code file fcountV03.asm:

● The switches debug and debugpulse must be set to 0.


● If a LCD is attached, cDisplay must be set to 1.
● If the attached LCD is 8-character-per-line cDisplay8 must be set to 1. For larger LCDs, cDisplay8 must be cleard to 0.
● If the attached LCD has a single line only, cDisplay2 must be set to 0. For two or more lines set this to 1.
● If the serial interface is attached and should be used, set cUart to 1.
● If the prescaler by 16 is connected to a different portbit than PC5, the symbols pPresc and pPrescD as well as bPresc is to be set accordingly.
● If the processor clock is different from 16 MHz, change cFreq accordingly.
● If the SIO's baudrate should be different from 9,600 bd, change cBaud.
● If the voltage divider for measuring voltages is not (1 M and 1 M), adjust cR1 and cR2 accordingly. If the displayed voltages are different from the input voltage, change cRin. Smaller values of cRin yield higher
displayed voltages.

3.2 Fuses

In its original form ATmega8 runs with its internal RC oscillator. To change this the fuses must be adjusted to the external xtal.

The following adjustments shown are with ATMEL's Studio:

In PonyProg 2000 the same looks like this:

Please note: After changing the fuses, the ATmega8 only works with an xtal attached.

3.3 Commented source code

The source code can be displayed in HTML format (here) and downloaded as assembler source code file (here). The text file ReadMe3.txt has additional hints for programming and operation.

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/fcount/fcount_m8.html1/20/2009 7:59:00 PM
http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm

; *******************************************************
; * Frequencycounter, RPM-Meter and Voltmeter *
; * for ATmega8 at 16 MHz crystal clock frequency *
; * with prescaler /1 or /16 *
; * Version 0.3 (C)2009 by info!at!avr-asm-tutorial.net *
; *******************************************************
;
.INCLUDE "m8def.inc"
;
.EQU debug = 0
.EQU debugpulse = 0
;
; Switches for connected hardware
;
.EQU cDisplay = 1 ; LCD display connected
.EQU cDisplay8 = 0 ; displays 8 characters per line instead of 16
.EQU cDisplay2 = 1 ; two line LCD display connected
.EQU cUart = 1 ; Uart active
; attached prescaler on port C
.EQU pPresc = PORTC ; prescaler by 16 output attached to port C
.EQU pPrescD = DDRC ; data direction of prescaler
.EQU bPresc = 5 ; bit 5 enables prescaler by 16
;
; ================================================
; Other hardware depending stuff
; ================================================
;
.EQU cFreq = 16000000 ; Clock frequency processor in cycles/s
.IF cUart
.EQU cBaud = 9600 ; If Uart active, define Baudrate
.ENDIF
.EQU bLcdE = 5 ; LCD E port bit on Port B
.EQU bLcdRs = 4 ; Lcd RS port bit on Port B
;
; ================================================
; Constants for voltage measurement
; ================================================
;
; Resistor network as pre-divider for the ADC
; --------------------------------------
; R1 R2(k) Meas Accur. MaxVoltage
; kOhm kOhm Volt mV/dig Volt
; --------------------------------------
; 1000 1000 5,12 5 10
; 1000 820 5,68 6 11
; 1000 680 6,32 6 12
; 1000 560 7,13 7 14
; 1000 470 8,01 8 15
; 1000 330 10,32 10 20
; 1000 270 12,04 12 23
; 1000 220 14,20 14 27
; 1000 180 16,78 16 32
; 1000 150 19,63 19 38
; 1000 120 23,98 23 46
; 1000 100 28,16 28 55
;
.EQU cR1 = 1000 ; Resistor between ADC input and measured voltage
.EQU cR2 = 1000 ; Resistor between ADC input and ground
.EQU cRin = 8250 ; Input resistance ADC, experimental
;
; Other sSoft switches
;
.EQU cNMode = 3 ; number of measurements before mode changes
.EQU cDecSep = '.' ; decimal separator for numbers displayed
.EQU c1kSep = ',' ; thousands separator
.EQU nMeasm = 4 ; number of measurements per second
.IF (nMeasm<4)||(nMeasm>7)
.ERROR "Number of measurements outside acceptable range"
.ENDIF
;
; ================================================
; Hardware connections
; ================================================
; ___ ___
; RESET |1 |_| 28| Prescaler divide by 16 output
; RXD |2 A 27|
; TXD |3 T 26|
; Time inp |4 M 25|
; |5 E 24| Mode select input, 0..2.56 V
; Count in |6 L 23| Voltage input, 0..2.56 V
; VCC |7 22| GND
; GND |8 A 21| AREF (+2.56 V, output)
; XTAL1 |9 T 20| AVCC input
; XTAL2 |10 m 19| SCK/LCD-E
; |11 e 18| MISO/LCD-RS
; |12 g 17| MOSI/LCD-D7
; |13 a 16| LCD-D6
; LCD-D4 |14 8 15| LCD-D5
; |_________|
;
;
; ================================================
; Derived constants
; ================================================
;
.EQU cR2c = (cR2 * cRin) / (cR2+cRin)
.EQU cMultiplier = (641 * (cR1+cR2c))/cR2c ; used for voltage multiplication
.EQU cMaxVoltage = 1024*cMultiplier/256 ; in mV
.EQU cSafeVoltage = (cMaxVoltage * 5000) / 2560
.EQU cTDiv = 1000/nMeasm ; interval per measurement update
; calculating the CTC and prescaler values for TC1 (frequency measurement)
.SET cCmp1F = cFreq/32 ; CTC compare value with counter prescaler = 8
.SET cPre1F = (1<<WGM12)|(1<<CS11) ; CTC and counter prescaler = 8
.IF cFreq>2097120
.SET cCmp1F = cFreq/256 ; CTC compare value with counter prescaler = 64
.SET cPre1F = (1<<WGM12)|(1<<CS11)|(1<<CS10) ; counter prescaler = 64
.ENDIF
.IF cFreq>16776960
.SET cCmp1F = cFreq/1024 ; CTC compare value with counter prescaler = 256
.SET cPre1F = (1<<WGM12)|(1<<CS12) ; counter prescaler = 256
.ENDIF
; calculating the CTC and counter prescaler values for TC2 (LCD/UART update)
.SET cCmp2 = cFreq/8000
.SET cPre2 = (1<<CS21) ; counter prescaler = 8
.IF cFreq>2040000
.SET cCmp2 = cFreq/32000
.SET cPre2 = (1<<CS21)|(1<<CS20) ; counter prescaler = 32
.ENDIF
.IF cFreq>8160000
.SET cCmp2 = cFreq/64000
.SET cPre2 = (1<<CS22) ; counter prescaler = 64
.ENDIF
.IF cFreq>16320000
.SET cCmp2 = cFreq/128000 ; counter prescaler = 128
.SET cPre2 = (1<<CS22)|(1<<CS20)
.ENDIF
;
; Uart constants
;
.IF cUart
.EQU cNul = $00
.EQU cClrScr = $0C
.EQU cCr = $0D
.EQU cLf = $0A
.ENDIF
;
; Debug definitions for testing
;
; (none)
;
; ================================================
; Register definitons
; ================================================
;
; R0 used for LPM and for calculation purposes
.DEF rRes1 = R1 ; Result byte 1
.DEF rRes2 = R2 ; Result byte 2
.DEF rRes3 = R3 ; Result byte 3
.DEF rRes4 = R4 ; Result byte 4
.DEF rDiv1 = R5 ; Divisor byte 1
.DEF rDiv2 = R6 ; Divisor byte 2
.DEF rDiv3 = R7 ; Divisor byte 3
.DEF rDiv4 = R8 ; Divisor byte 4
.DEF rCpy1 = R9 ; Copy byte 1
.DEF rCpy2 = R10 ; Copy byte 2
.DEF rCpy3 = R11 ; Copy byte 3
.DEF rCpy4 = R12 ; Copy byte 4
.DEF rCtr1 = R13 ; Counter/Timer byte 1
.DEF rCtr2 = R14 ; Counter/Timer byte 2
.DEF rCtr3 = R15 ; Counter/Timer byte 3
.DEF rmp = R16 ; Multipurpose register outside interrupts
.DEF rimp = R17 ; Multipurpose register inside interrupts
.DEF rSreg = R18 ; Save status register inside interrupts
.DEF rTDiv = R19 ; Internal divider for TC2 count down
.DEF rMode = R20 ; Current mode of operation
.DEF rNMode = R21 ; Number of inadequate measurements
.DEF rir = R22 ; interrim calculation register
.DEF rFlg = R23 ; Flag register
.EQU bCyc = 2 ; measure cycle ended
.EQU bMode = 3 ; measuring mode, 1 = frequency, 0 = time
.EQU bEdge = 4 ; measured edge, 1 = rising, 0 = falling
.EQU bOvf = 5 ; overflow bit
.EQU bAdc = 6 ; ADC conversion complete flag bit
.EQU bUartRxLine = 7 ; Uart line complete flag bit
.DEF rDelL = R24 ; delay counter for LCD, LSB
.DEF rDelH = R25 ; dto., MSB
; X = R26..R27 used for calculation purposes
; Y = R28..R29: free
; Z = R30..R31 used for LPM and calculation purposes
;
; ================================================
; SRAM definitions
; ================================================
;
.DSEG
.ORG Sram_Start
;
; Result display space in SRAM
;
sResult:
.BYTE 32
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
;
.IF cUart
.EQU UartRxbLen = 38 ; Buffer length in bytes
;
sUartFlag: ; flag register for Uart
.BYTE 1
.EQU bUMonU = 0 ; displays voltage over Uart
.EQU bUMonF = 1 ; displays frequency over Uart
; free: bits 2..7
sUartMonUCnt: ; counter for Monitoring voltage
.BYTE 1
sUartMonURpt: ; counter preset for monitoring voltage
.BYTE 1
sUartMonFCnt: ; counter for Monitoring frequency
.BYTE 1
sUartMonFRpt: ; counter preset for monitoring voltage
.BYTE 1
sUartRxBp: ; buffer pointer
.BYTE 1
sUartRxBs: ; buffer
.BYTE UartRxbLen
sUartRxBe: ; buffer end
.ENDIF
;
; Main interval timer characteristics
;
sTMeas: ; ms per measuring interval (default: 250)
.BYTE 1
;
; ADC result
;
sAdc0L: ; ADC result, channel 0, LSB
.BYTE 1
sAdc0H: ; ADC result, channel 0, MSB
.BYTE 1
sAdc1L: ; ADC result, channel 1, LSB
.BYTE 1
sAdc1H: ; ADC result, channel 1, MSB
.BYTE 1
;
; Interim storage for counter value during time measurement
;
sCtr:
.BYTE 4
;
; ================================================
; Selected mode flags
; ================================================
;
; Mode Measuring Prescale Display
; ---------------------------------------------
; 0 Frequency 16 Frequency
; 1 Frequency 1 Frequency
; 2 Time HL 1 Frequency
; 3 Time HL 1 Rounds per Minute
; 4 Time HL 1 Time
; 5 Time H 1 Time
; 6 Time L 1 Time
; 7 PW ratio H 1 Pulse width ratio H %
; 8 PW ratio L 1 Pulse width ratio L %
; 9 none - Voltage only
; (for a single line LCD)
;
.EQU cModeFrequency16 = 0
.EQU cModeFrequency = 1
.EQU cModeTimeFreq = 2
.EQU cModeTimeRpm = 3
.EQU cModeTimeTimeHL = 4
.EQU cModeTimeTimeH = 5
.EQU cModeTimeTimeL = 6
.EQU cModeTimePwrH = 7
.EQU cModeTimePwrL = 8
.EQU cModeVoltage = 9
;
sModeSlct: ; Selected mode
.BYTE 1
sModeNext: ; next selected mode
.BYTE 1
;
; ==================================================
; Info on timer and counter interrupt operation
; ==================================================
;
; Clock => Presc2 => TC2 => CTC => rTDiv =>
; ADC0 conversion => ADC1 conversion => bAdc-flag
;
; Main interval timer TC2
; - uses TC2 as 8-bit-CTC, with compare interrupt
; - starts a ADC conversion
; - on ADC conversion complete:
; * store ADC result
; * convert ADC result
; * if a new counter result: convert this
; * if Uart connected and monitoring f/U: display on Uart
; * if LCD connected and display mode: display f/U result
;
; Operation at 16 MHz clock:
; cFreq => Prescaler/128 => CTC(125) => rTDiv(250)
; 16MHz => 125 kHz => 1 kHz => 4 Hz
;
; Frequeny counting modes (Mode = 0 and 1)
; - uses TC0 as 8-bit-counter to count positive edges
; - uses TC1 as 16-bit-counter to time-out the counter after 250 ms
;
; Timer modes (Mode = 2 to 8)
; - uses edge detection on external INT0 for timeout
; - uses TC1 as 16-bit-counter to time-out from edge to edge
;
; Voltage only (Mode = 9)
; - Timers TC0 and TC1 off
; - Timer TC2 times interval
;
; ==============================================
; Reset and Interrupt Vectors starting here
; ==============================================
;
.CSEG
.ORG $0000
;
; Reset/Intvectors
;
rjmp Main ; Reset
rjmp Int0Int; Int0
reti ; Int1
rjmp TC2CmpInt ; TC2 Comp
reti ; TC2 Ovf
reti ; TC1 Capt
rjmp Tc1CmpAInt ; TC1 Comp A
reti ; TC1 Comp B
rjmp Tc1OvfInt ; TC1 Ovf
rjmp TC0OvfInt ; TC0 Ovf
reti ; SPI STC
.IF cUart
rjmp SioRxcIsr ; USART RX
.ELSE
reti ; USART RX
.ENDIF
reti ; USART UDRE
reti ; USART TXC
rjmp AdcCcInt ; ADC Conv Compl
reti ; EERDY
reti ; ANA_COMP
reti ; TWI
reti ; SPM_RDY
;
; =============================================
;
; Interrupt Service Routines
;
; =============================================
;
; TC2 Compare Match Interrupt
; counts rTDiv down, if zero: starts an AD conversion
;
TC2CmpInt:
in rSreg,SREG ; save SREG
dec rTDiv ; count down
brne TC2CmpInt1 ; not zero, interval not ended
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp ; start ADC conversion
lds rTDiv,sTMeas ; restart interval timer
TC2CmpInt1:
out SREG,rSreg ; restore SREG
reti
;
; External Interrupt INT0 Service Routine
; active in modes 2 to 6 (measuring the signal duration),
; detects positive going edges of the input
; INT1, TC1 is in free running mode,
; reads the current counter state of TC1,
; copies it to the result registers,
; clears the counter and restarts it
;
Int0Int:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp Int0Int1 ; 4, no, last result hasn't been read
in rCpy1,TCNT1L ; 4, read timer 1 LSB
in rCpy2,TCNT1H ; 5, dto., MSB
mov rCpy3,rCtr2 ; 6, copy the counter bytes
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
cbr rFlg,1<<bEdge ; 9, set falling edge
sbic PIND,2 ; 10/11, check if input = 0
sbr rFlg,1<<bEdge ; 11, no, set edge flag to rising
Int0Int1: ; 4/11
ldi rimp,0 ; 5/12, reset the timer
out TCNT1H,rimp ; 6/13, set TC1 zero to restart
out TCNT1L,rimp ; 7/14
mov rCtr1,rimp ; 8/15, clear the upper bytes
mov rCtr2,rimp ; 9/16
mov rCtr3,rimp ; 10/17
out SREG,rSreg ; 11/18, restore SREG
reti ; 15/22
;
; TC1 Compare Match A Interrupt Service Routine
; active in modes 0 and 1 (measuring the number of
; sigals on the T1 input), timeout every 0.25s,
; reads the counter TC0, copies the count to
; the result registers and clears TC0
;
Tc1CmpAInt:
in rSreg,SREG ; 1, save SREG
sbrc rFlg,bCyc ; 2/3, check if cycle flag signals ok for copy
rjmp TC1CmpAInt1 ; 4, no, last result hasn't been read
in rCpy1,TCNT0 ; 4, read counter TC0
mov rCpy2,rCtr1 ; 5, copy counter bytes to result
mov rCpy3,rCtr2 ; 6
mov rCpy4,rCtr3 ; 7
sbr rFlg,1<<bCyc ; 8, set cycle end flag bit
Tc1CmpAInt1: ; 4/8
ldi rimp,0 ; 5/9, clear counter
out TCNT0,rimp ; 6/10
mov rCtr1,rimp ; 7/11, clear counter bytes
mov rCtr2,rimp ; 8/12
mov rCtr3,rimp ; 9/13
out SREG,rSreg ; 10/14, restore SREG
reti ; 14/18
;
; TC1 Overflow Interrupt Service Routine
; active in modes 2 to 6 counting clock cycles to measure time
; increases the upper bytes and detects overflows
;
Tc1OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr2 ; 2, increase byte 3 of the counter
brne Tc1OvfInt1 ; 3/4, no overflow
inc rCtr3 ; 4, increase byte 4 of the counter
brne Tc1OvfInt1 ; 5/6, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 6, set overflow and end of cycle bit
Tc1OvfInt1: ; 4/6
out SREG,rSreg ; 5/7, restore SREG
reti ; 9/11
;
; TC0 Overflow Interrupt Service Routine
; active in modes 0 and 1 counting positive edges on T1
; increases the upper bytes and detects overflows
;
Tc0OvfInt:
in rSreg,SREG ; 1, save SREG
inc rCtr1 ; 2, increase byte 2 of the counter
brne Tc0OvfInt1 ; 3/4, no overflow
inc rCtr2 ; 4, increase byte 3 of the counter
brne Tc0OvfInt1 ; 5/6, no overflow
inc rCtr3 ; 6, increase byte 4 of the counter
brne Tc0OvfInt1 ; 7/8, no overflow
sbr rFlg,(1<<bOvf)|(1<<bCyc) ; 8, set overflow bit
Tc0OvfInt1: ; 4/6/8
out SREG,rSreg ; 5/7/9, restore SREG
reti ; 9/11/13
;
; Uart RxC Interrupt Service Routine
; receives a character, signals errors, echoes it back,
; puts it into the SRAM line buffer, checks for carriage
; return characters, if yes echoes additional linefeed
; and sets line-complete flag
;
.IF cUart
SioRxCIsr:
in rSreg,SREG ; 1, Save SReg
in rimp,UCSRA ; 2, Read error flags
andi rimp,(1<<FE)|(1<<DOR)|(1<<PE) ; 3, isolate error bits
in rimp,UDR ; 4, read character from UART
breq SioRxCIsr1 ; 5/6, no errors
ldi rimp,'*' ; 6, signal an error
out UDR,rimp ; 7
rjmp SioRxCIsr4 ; 9, return from int
SioRxCIsr1: ; 6
out UDR,rimp ; 7, echo the character
push ZH ; 9, Save Z register
push ZL ; 11
ldi ZH,HIGH(sUartRxBs) ; 12, Load Position for next RX char
lds ZL,sUartRxBp ; 14
st Z+,rimp ; 16, save char in buffer
cpi ZL,LOW(sUartRxBe+1) ; 17, End of buffer?
brcc SioRxCIsr2 ; 18/19, Buffer overflow
sts sUartRxBp,ZL ; 20, Save next pointer position
SioRxCIsr2: ; 19/20
cpi rimp,cCr ; 20/21, Carriage Return?
brne SioRxCIsr3 ; 21/22/23, No, go on
ldi rimp,cLf ; 22/23, Echo linefeed
out UDR,rimp ; 23/24
sbr rFlg,(1<<bUartRxLine) ; 24/25, Set line complete flag
rjmp SioRxCIsr3a
SioRxCIsr3: ; 22/23/24/25
cpi rimp,cLf
brne SioRxCIsr3a
sbr rFlg,(1<<bUartRxLine)
SioRxCIsr3a:
pop ZL ; 24/25/26/27, restore Z-register
pop ZH ; 26/27/28/29
SioRxCIsr4: ; 9/26/27/28/29
out SREG,rSreg ; 10/27/28/29/30, restore SREG
reti ; 14/31/32/33/34, return from Int
.ENDIF
;
; ADC has completed a conversion
; used in all modes, ADC has completed a conversion
; if ADMUX channel is 0 then set ADMUX=1 and start
; another coversion
; if ADMUX channel is 1 he set ADMUX=0, disable the ADC
; and set teh ADC cycle end flag
;
.EQU cStopAdc = (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
.EQU cStartAdc = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|cStopAdc
AdcCcInt:
in rSreg,SREG ; 1, save SREG
in rimp,ADMUX ; 2, read the current channel info
sbrc rimp,0 ; 3/4, jump if channel = 0
rjmp AdcCcInt1 ; 5
sbr rimp,1 ; 5, set channel MUX to one
out ADMUX,rimp ; 6
in rimp,ADCL ; 7, read result LSB
sts sAdc0L,rimp ; 9, store result LSB
in rimp,ADCH ; 10, read result MSB
sts sAdc0H,rimp ; 12, store result MSB
ldi rimp,cStartAdc
out ADCSRA,rimp ; 14, start next conversion
out SREG,rSreg ; 15, restore SREG
reti ; 19
AdcCcInt1: ; 5
cbr rimp,1 ; 6, set MUX to channel 0
out ADMUX,rimp ; 7
in rimp,ADCL ; 8, read result LSB
sts sAdc1L,rimp ; 10, store result LSB
in rimp,ADCH ; 11, read result MSB
sts sAdc1H,rimp ; 13, store result MSB
sbr rFlg,1<<bAdc ; 14, set flag bit
ldi rimp,cStopAdc ; 15, ADC off
out ADCSRA,rimp ; 16, switch ADC off
out SREG,rSreg ; 17, restore SREG
reti ; 21
;
; ================================================
; Common subroutines
; ================================================
;
; Setting timer/counter modes for measuring
;
SetModeNext:
rcall ClrTc ; clear the timers TC0 and TC1, disable INT0
lds rmp,sModeNext ; read next mode
mov rMode,rmp ; copy to current mode
ldi ZH,HIGH(SetModeTab)
ldi ZL,LOW(SetModeTab)
add ZL,rmp
ldi rmp,0
adc ZH,rmp
ijmp
; Table mode setting
SetModeTab:
rjmp SetMode0 ; f div 16, f
rjmp SetMode1 ; f, f
rjmp SetModeT ; t, f
rjmp SetModeT ; t, u
rjmp SetModeT ; t, t
rjmp SetModeE ; th, t
rjmp SetModeE ; tl, t
rjmp SetModeE ; th, p
rjmp SetModeE ; tl, p
ret ; U, U
;
; Set counters/timers to mode 0
; TC0 counts input signals (positive edges)
; TC1 times the gate at 250 ms
; INT0 disabled
;
SetMode0:
cbi pPresc,bPresc ; enable prescaler
rjmp SetModeF ; frequency measurement
;
; Set counters/timers to mode 1
;
SetMode1:
sbi pPresc,bPresc ; disable prescaler
; Set timer/counter mode to frequency measurement
SetModeF:
ldi rmp,HIGH(cCmp1F) ; set the compare match high value
out OCR1AH,rmp
ldi rmp,LOW(cCmp1F) ; set the compare match low value
out OCR1AL,rmp
ldi rmp,0xFF ; disable the compare match B
out OCR1BH,rmp
out OCR1BL,rmp
ldi rmp,0 ; CTC mode
out TCCR1A,rmp
ldi rmp,cPre1F ; set the prescaler value for TC1
out TCCR1B,rmp
ldi rmp,(1<<CS02)|(1<<CS01)|(1<<CS00) ; count rising edges on T0
out TCCR0,rmp
ldi rmp,(1<<OCIE2)|(1<<OCIE1A)|(1<<TOIE0) ; enable TC2Cmp, TC1CmpAInt and
TC0OverflowInt
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement
;
SetModeT:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00) ; sleep enable, positive edges on INT0 interrupt
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
; Set timer/counter mode to time measurement, all edges
;
SetModeE:
sbi pPresc,bPresc ; disable prescaler
ldi rmp,0 ; timing mode
out TCCR1A,rmp
ldi rmp,1<<CS10 ; count with prescaler = 1
out TCCR1B,rmp
ldi rmp,(1<<SE)|(1<<ISC00) ; sleep enable, any logical change on INT0 interrupts
out MCUCR,rmp
ldi rmp,1<<INT0 ; enable INT0 interrupt
out GICR,rmp
ldi rmp,(1<<OCIE2)|(1<<TOIE1) ; enable TC2Cmp, TC1Ovflw
out TIMSK,rmp
ret
;
;
; clears the timers and resets the upper bytes
;
ClrTc:
clr rmp ; disable INT0
out GICR,rmp
clr rmp ; stop the counters/timers
out TCCR0,rmp ; stop TC0 counting/timing
out TCCR1B,rmp ; stop TC1 counting/timing
out TCNT0,rmp ; clear TC0
out TCNT1L,rmp ; clear TC1
out TCNT1H,rmp
clr rCtr1 ; clear upper bytes
clr rCtr2
clr rCtr3
ldi rmp,1<<OCIE2 ; enable only output compare of TC2 ints
out TIMSK,rmp ; timer int disable
ret
;
; =======================================================
; Math routines
; =======================================================
;
; Divides cFreq/256 by the timer value in rDiv4:rDiv3:rDiv2:rDiv1
; yields frequency in R4:R3:R2:(Fract):R1
;
Divide:
clr rmp ; rmp:R0:ZH:ZL:XH:XL is divisor
clr R0
clr ZH
ldi ZL,BYTE3(cFreq/256) ; set divisor
ldi XH,BYTE2(cFreq/256)
ldi XL,BYTE1(cFreq/256)
clr rRes1 ; set result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
Divide1:
lsl XL ; multiply divisor by 2
rol XH
rol ZL
rol ZH
rol R0
rol rmp
cp ZL,rDiv1 ; compare with divident
cpc ZH,rDiv2
cpc R0,rDiv3
cpc rmp,rDiv4
brcs Divide2
sub ZL,rDiv1
sbc ZH,rDiv2
sbc R0,rDiv3
sbc rmp,rDiv4
sec
rjmp Divide3
Divide2:
clc
Divide3:
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc Divide1
ret
;
; Multiply measured time in rRes4:rRes3:rRes2:rRes1 by 65536 / fq(MHz)
; rmp:R0 are the upper bytes of the input
; ZH:ZL:rDiv4:rDiv3:rDiv2:rDiv1 is the interim result
; XH:XL is the multiplicator
; result is in rRes4:rRes3:rRes2:rRes1
;
.EQU cMulti = 65536000 / (cFreq/1000)
;
Multiply:
ldi XH,HIGH(cMulti) ; set multiplicator
ldi XL,LOW(cMulti)
clr ZH
clr ZL
clr rDiv4
clr rDiv3
clr rDiv2
clr rDiv1
clr R0
clr rmp
Multiply1:
cpi XL,0
brne Multiply2
cpi XH,0
breq Multiply4
Multiply2:
lsr XH
ror XL
brcc Multiply3
add rDiv1,rRes1
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
adc ZL,R0
adc ZH,rmp
Multiply3:
lsl rRes1
rol rRes2
rol rRes3
rol rRes4
rol R0
rol rmp
rjmp Multiply1
Multiply4:
ldi rmp,128 ; round result
clr R0
add rDiv2,rmp
adc rDiv3,R0
adc rDiv4,R0
adc ZL,R0
adc ZH,R0
mov rRes1,rDiv3 ; move result
mov rRes2,rDiv4
mov rRes3,ZL
mov rRes4,ZH
ret
;
; Display seconds at buffer end
;
DisplSec:
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'u'
st X+,rmp
ldi rmp,'s'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ret
;
; An overflow has occurred during pulse width calculation
;
PulseOvflw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
st X+,rmp
.IF cDisplay8
ldi ZH,HIGH(2*TxtPOvflw8)
ldi ZL,LOW(2*TxtPOvflw8)
ldi rmp,7
.ELSE
ldi ZH,HIGH(2*TxtPOvflw16)
ldi ZL,LOW(2*TxtPOvflw16)
ldi rmp,15
.ENDIF
PulseOvflw1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne PulseOvflw1
ret
.IF cDisplay8
TxtPOvflw8:
.DB ":error! "
.ELSE
TxtPOvflw16:
.DB ":error calcul.! "
.ENDIF
;
; ======================================================
; Pulse width calculations
; ======================================================
;
; Calculate the pulse width ratio
; active cycle time is in rDelH:rDelL:R0:rmp
; total cycle time is in rDiv
; result will be in rRes
; overflow: carry flag is set
;
CalcPwO: ; overflow
sec
ret
CalcPw:
mov rRes1,rmp ; copy active cycle time to rRes
mov rRes2,R0
mov rRes3,rDelL
mov rRes4,rDelH
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO ; overflow
mov XL,rRes1 ; copy to Z:X
mov XH,rRes2
mov ZL,rRes3
mov ZH,rRes4
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
brcs CalcPwO
add rRes1,XL ; * 24
adc rRes2,XH
adc rRes3,ZL
adc rRes4,ZH
clr ZH ; clear the four MSBs of divisor
clr ZL
clr XH
mov XL,rDelH ; * 256
mov rDelH,rDelL
mov rDelL,R0
mov R0,rmp
clr rmp
lsl R0 ; * 512
rol rDelL
rol rDelH
rol XL
rol XH
lsl R0 ; * 1024
rol rDelL
rol rDelH

http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm (1 of 4)1/20/2009 7:59:09 PM


http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm

rol XL
rol XH
sub rmp,rRes1 ; * 1000
sbc R0,rRes2
sbc rDelL,rRes3
sbc rDelH,rRes4
sbc XL,ZH
sbc XH,ZH
cp XL,rDiv1 ; overflow?
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcc CalcPwO
clr rRes1 ; clear result
inc rRes1
clr rRes2
clr rRes3
clr rRes4
CalcPw1: ; dividing loop
lsl rmp ; multiply by 2
rol R0
rol rDelL
rol rDelH
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1 ; compare with divisor
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw2 ; smaller, roll zero in
sub XL,rDiv1 ; subtract divisor
sbc XH,rDiv2
sbc ZL,rDiv3
sbc ZH,rDiv4
sec ; roll one in
rjmp CalcPw3
CalcPw2:
clc
CalcPw3: ; roll result
rol rRes1
rol rRes2
rol rRes3
rol rRes4
brcc CalcPw1 ; roll on
lsl rDelL ; round result
rol XL
rol XH
rol ZL
rol ZH
cp XL,rDiv1
cpc XH,rDiv2
cpc ZL,rDiv3
cpc ZH,rDiv4
brcs CalcPw4
ldi rmp,1 ; round up
add rRes1,rmp
ldi rmp,0
adc rRes2,rmp
adc rRes3,rmp
adc rRes4,rmp
CalcPw4:
tst rRes4 ; check > 1000
brne CalcPwE
tst rRes3
brne CalcPwE
ldi rmp,LOW(1001)
cp rRes1,rmp
ldi rmp,HIGH(1001)
cpc rRes2,rmp
brcc CalcPwE
clc ; no error
ret
CalcPwE: ; error
sec
ret
;
; Display the binary in R2:R1 in the form " 100,0%"
;
DisplPw:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
ldi rmp,' '
st X+,rmp
st X+,rmp
clr R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecX2
ldi ZH,HIGH(100)
ldi ZL,LOW(100)
rcall DisplDecX2
ldi ZL,10
inc R0
rcall DisplDecX2
ldi rmp,cDecSep
st X+,rmp
ldi rmp,'0'
add rmp,rRes1
st X+,rmp
ldi rmp,'%'
st X+,rmp
.IF ! cDisplay8
ldi rmp,8
ldi ZL,' '
DisplPw1:
st X+,ZL
dec rmp
brne DisplPw1
.ENDIF
ret
;
; If the first characters in the result buffer are empty,
; place the character in ZL here and add equal, if possible
;
DisplMode:
ldi XH,HIGH(sResult+1) ; point to result buffer
ldi XL,LOW(sResult+1)
ld rmp,X ; read second char
cpi rmp,' '
brne DisplMode1
ldi rmp,'='
st X,rmp
DisplMode1:
sbiw XL,1
ld rmp,X ; read first char
cpi rmp,' '
brne DisplMode2
st X,ZL
DisplMode2:
ret
;
;=================================================
; Display binary numbers as decimal
;=================================================
;
; Converts a binary in R2:R1 to a digit in X
; binary in Z
;
DecConv:
clr rmp
DecConv1:
cp R1,ZL ; smaller than binary digit?
cpc R2,ZH
brcs DecConv2 ; ended subtraction
sub R1,ZL
sbc R2,ZH
inc rmp
rjmp DecConv1
DecConv2:
tst rmp
brne DecConv3
tst R0
brne DecConv3
ldi rmp,' ' ; suppress leading zero
rjmp DecConv4
DecConv3:
subi rmp,-'0'
DecConv4:
st X+,rmp
ret
;
; Display fractional number in R3:R2:(Fract)R1
;
DisplFrac:
ldi XH,HIGH(sResult)
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
.ENDIF
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DisplDecY2
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DisplDecY2
.IF ! cDisplay8
ldi rmp,c1kSep
tst R0
brne DisplFrac0
ldi rmp,' '
DisplFrac0:
st X+,rmp
.ENDIF
ldi ZL,100
rcall DisplDecY1
ldi ZL,10
rcall DisplDecY1
ldi rmp,'0'
add rmp,R2
st X+,rmp
tst R1 ; fraction = 0?
brne DisplFrac1
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
st X+,rmp
st X+,rmp
st X+,rmp
.ENDIF
ret
DisplFrac1:
ldi rmp,cDecSep
st X+,rmp
.IF cDisplay8
ldi ZL,2
.ELSE
ldi ZL,3
.ENDIF
DisplFrac2:
clr rRes3
clr rRes2
mov R0,rRes1 ; * 1
lsl rRes1 ; * 2
adc rRes2,rRes3
lsl rRes1 ; * 4
rol rRes2
add rRes1,R0 ; * 5
adc rRes2,rRes3
lsl rRes1 ; * 10
rol rRes2
ldi rmp,'0'
add rmp,rRes2
st X+,rmp
dec ZL
brne DisplFrac2
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X+,rmp
.ENDIF
ret
;
; Convert a decimal in R4:R3:R2, decimal in ZH:ZL
;
DisplDecY2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY2a:
cp rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecY2b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecY2a
DisplDecY2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY2c
ldi rmp,' '
DisplDecY2c:
st X+,rmp
ret
;
; Convert a decimal decimal in R:R2, decimal in ZL
;
DisplDecY1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; overflow byte
DisplDecY1a:
cp rRes2,ZL
cpc rRes3,rDiv2
brcs DisplDecY1b ; ended
sub rRes2,ZL ; subtract
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecY1a
DisplDecY1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecY1c
ldi rmp,' '
DisplDecY1c:
st X+,rmp
ret
;
; Display a 4-byte-binary in decimal format on result line 1
; 8-bit-display: "12345678"
; 16-bit-display: " 12.345.678 Hz "
;
Displ4Dec:
ldi rmp,BYTE1(100000000) ; check overflow
cp rRes1,rmp
ldi rmp,BYTE2(100000000)
cpc rRes2,rmp
ldi rmp,BYTE3(100000000)
cpc rRes3,rmp
ldi rmp,BYTE4(100000000)
cpc rRes4,rmp
brcs Displ4Dec1
rjmp CycleOvf
Displ4Dec1:
clr R0 ; suppress leading zeroes
ldi XH,HIGH(sResult) ; X to result buffer
ldi XL,LOW(sResult)
.IF ! cDisplay8
ldi rmp,' ' ; clear the first two digits
st X+,rmp
st X+,rmp
.ENDIF
ldi ZH,BYTE3(10000000) ; 10 mio
ldi ZL,BYTE2(10000000)
ldi rmp,BYTE1(10000000)
rcall DisplDecX3
ldi ZH,BYTE3(1000000) ; 1 mio
ldi ZL,BYTE2(1000000)
ldi rmp,BYTE1(1000000)
rcall DisplDecX3
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec2
ldi rmp,' '
Displ4Dec2:
st X+,rmp
.ENDIF
ldi ZH,BYTE3(100000) ; 100 k
ldi ZL,BYTE2(100000)
ldi rmp,BYTE1(100000)
rcall DisplDecX3
ldi ZH,HIGH(10000) ; 10 k
ldi ZL,LOW(10000)
rcall DisplDecX2
ldi ZH,HIGH(1000) ; 1 k
ldi ZL,LOW(1000)
rcall DisplDecX2
.IF ! cDisplay8
ldi rmp,c1kSep ; set separator
tst R0
brne Displ4Dec3
ldi rmp,' '
Displ4Dec3:
st X+,rmp
.ENDIF
ldi ZL,100 ; 100
rcall DisplDecX1
ldi ZL,10
rcall DisplDecX1
ldi rmp,'0' ; 1
add rmp,R1
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL:rmp
;
DisplDecX3:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; subtractor for byte 4
DisplDecX3a:
cp rRes1,rmp ; compare
cpc rRes2,ZL
cpc rRes3,ZH
cpc rRes4,rDiv2
brcs DisplDecX3b ; ended
sub rRes1,rmp ; subtract
sbc rRes2,ZL
sbc rRes3,ZH
sbc rRes4,rDiv2
inc rDiv1
rjmp DisplDecX3a
DisplDecX3b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX3c
ldi rmp,' '
DisplDecX3c:
st X+,rmp
ret
;
; Convert a decimal in R3:R2:R1, decimal in ZH:ZL
;
DisplDecX2:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX2a:
cp rRes1,ZL
cpc rRes2,ZH
cpc rRes3,rDiv2
brcs DisplDecX2b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,ZH
sbc rRes3,rDiv2
inc rDiv1
rjmp DisplDecX2a
DisplDecX2b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX2c
ldi rmp,' '
DisplDecX2c:
st X+,rmp
ret
;
; Convert a decimal in R2:R1, decimal in ZL
;
DisplDecX1:
clr rDiv1 ; rDiv1 is counter
clr rDiv2 ; next byte overflow
DisplDecX1a:
cp rRes1,ZL
cpc rRes2,rDiv2
brcs DisplDecX1b ; ended
sub rRes1,ZL ; subtract
sbc rRes2,rDiv2
inc rDiv1
rjmp DisplDecX1a
DisplDecX1b:
ldi rmp,'0'
add rmp,rDiv1
add R0,rDiv1
tst R0
brne DisplDecX1c
ldi rmp,' '
DisplDecX1c:
st X+,rmp
ret
;
;=================================================
; Delay routines
;=================================================
;
Delay10ms:
ldi rDelH,HIGH(10000)
ldi rDelL,LOW(10000)
rjmp DelayZ
Delay15ms:
ldi rDelH,HIGH(15000)
ldi rDelL,LOW(15000)
rjmp DelayZ
Delay4_1ms:
ldi rDelH,HIGH(4100)
ldi rDelL,LOW(4100)
rjmp DelayZ
Delay1_64ms:
ldi rDelH,HIGH(1640)
ldi rDelL,LOW(1640)
rjmp DelayZ
Delay100us:
clr rDelH
ldi rDelL,100
rjmp DelayZ
Delay40us:
clr rDelH
ldi rDelL,40
rjmp DelayZ
;
; Delays execution for Z microseconds
;
DelayZ:
.IF cFreq>18000000
nop
nop
.ENDIF
.IF cFreq>16000000
nop
nop
.ENDIF
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
sbiw rDelL,1 ; 2
brne DelayZ ; 2
ret
;
; =========================================
; Main Program Start
; =========================================
;
main:
ldi rmp,HIGH(RAMEND) ; set stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
clr rFlg ; set flags to default
;
.IF debug
.EQU number = 100000000
ldi rmp,BYTE4(number)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(number)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(number)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(number)
mov rRes1,rmp
mov rDiv1,rmp
rcall CycleM6
beloop: rjmp beloop
.ENDIF
.IF debugpulse
.EQU nhigh = 100000000
.EQU nlow = 15000
ldi rmp,BYTE4(nhigh)
sts sCtr+3,rmp
ldi rmp,BYTE3(nhigh)
sts sCtr+2,rmp
ldi rmp,BYTE2(nhigh)
sts sCtr+1,rmp
ldi rmp,BYTE1(nhigh)
sts sCtr,rmp
ldi rmp,BYTE4(nlow)
mov rRes4,rmp
mov rDiv4,rmp
ldi rmp,BYTE3(nlow)
mov rRes3,rmp
mov rDiv3,rmp
ldi rmp,BYTE2(nlow)
mov rRes2,rmp
mov rDiv2,rmp
ldi rmp,BYTE1(nlow)
mov rRes1,rmp
mov rDiv1,rmp
sbr rFlg,1<<bEdge
rcall CycleM7
bploop: rjmp bploop
.ENDIF
;
; Clear the output storage
;
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,' '
mov R0,rmp
ldi rmp,32
main1:
st Z+,R0
dec rmp
brne main1
;
; Init the Uart
;
.IF cUart
rcall UartInit
ldi rmp,1<<bUMonU ; monitor U over Uart
sts sUartFlag,rmp
ldi rmp,20 ; 5 seconds
sts sUartMonURpt,rmp ; set repeat default value
ldi rmp,1
sts sUartMonUCnt,rmp
ldi rmp,4 ; 1 seconds
sts sUartMonFCnt,rmp
.ENDIF
;
; Init the LCD
;
.IF cDisplay
rcall LcdInit
.ENDIF
;
; Disable the Analog comparator
;
ldi rmp,1<<ACD
out ACSR,rmp
;
; Disable the external prescaler by 16
;
sbi pPrescD,bPresc ; set prescaler port bit to output
sbi pPresc,bPresc ; disable the prescaler
;
; Init the ADC
;
ldi rmp,(1<<REFS1)|(1<<REFS0) ; int.ref, channel 0
out ADMUX,rmp
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; prescaler = 128
out ADCSRA,rmp
;
; Start main interval timer
;
ldi rmp,cCmp2 ; set Compare Match
out OCR2,rmp
ldi rmp,cPre2|(1<<WGM21) ; CTC mode and prescaler
out TCCR2,rmp
;
; Start timer/counter TC2 interrupts
;
ldi rmp,(1<<OCIE2) ; Interrupt mask
out TIMSK,rmp
;
; Set initial mode to mode 1
;
ldi rmp,1 ; initial mode = 1
sts sModeNext,rmp
rcall SetModeNext
;
sei ; enable interrupts
;
loop:
sleep ; send CPU to sleep
nop
sbrc rFlg,bCyc ; check cycle end
rcall Cycle
sbrc rFlg,bAdc
rcall Interval
.IF cUart
sbrc rFlg,bUartRxLine ; check line complete
rcall UartRxLine ; call line complete
.ENDIF
rjmp loop ; go to sleep
;
; Timer interval for calculation and display
;
Interval:
cbr rFlg,1<<bAdc ; clear flag
lds ZL,sAdc1L ; read ADC channel 1 value
lds ZH,sAdc1H
mov XL,ZL ; copy to X
mov XH,ZH
lsl ZL ; multiply by 2
rol ZH
lsl ZL ; multiply by 4
rol ZH
add ZL,XL ; multiply by 5
adc ZH,XH
lsr ZH ; multiply by 2.5
ror ZL
cpi ZH,10 ; larger than 9?
brcs Interval1
ldi ZH,9 ; set to 9
Interval1:
sts sModeNext,ZH ; store next mode
cp rMode,ZH ; new mode?
breq Interval2 ; continue current mode
rcall SetModeNext ; start new mode
Interval2:
.IF cUart || cDisplay
lds R0,sAdc0L ; read ADC value
lds R1,sAdc0H
rcall cAdc2U ; convert to text
.IF cDisplay
rcall LcdDisplayFT
rcall LcdDisplayU
.ENDIF
.IF cUart
rcall UartMonU
.ENDIF
.ENDIF
ret
;
; Frequency/Time measuring cycle ended, calculate results
;
Cycle:
sbrc rFlg,bOvf ; check overflow
rjmp CycleOvf ; jump to overflow
mov rRes1,rCpy1 ; copy counter
mov rRes2,rCpy2
mov rRes3,rCpy3
mov rRes4,rCpy4
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
mov rDiv1,rRes1 ; copy again
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
.IF cUart
ldi ZH,HIGH(UartMonF) ; put monitoring frequency on stack
ldi ZL,LOW(UartMonF)
push ZL
push ZH
.ENDIF
ldi ZH,HIGH(CycleTab) ; point to mode table
ldi ZL,LOW(CycleTab)
add ZL,rMode ; displace table by mode
brcc Cycle1
inc ZH
Cycle1:
ijmp ; call the calculation routine
; overflow occurred
CycleOvf:
cbr rFlg,(1<<bCyc)|(1<<bOvf) ; clear cycle flag and overflow
ldi XH,HIGH(sResult) ; point to result buffer
ldi XL,LOW(sResult)
.IF cDisplay8
ldi ZH,HIGH(2*TxtOvf8) ; point to short message
ldi ZL,LOW(2*TxtOvf8)
ldi rmp,8
.ELSE
ldi ZH,HIGH(2*TxtOvf16) ; point to long message
ldi ZL,LOW(2*TxtOvf16)
ldi rmp,16
.ENDIF
CycleOvf1:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne CycleOvf1
ret
;
.IF cDisplay8
TxtOvf8:
.DB " ovflow"
.ELSE
TxtOvf16:
.DB " overflow "
.ENDIF
; Table with routines for the 8 modes
CycleTab:
rjmp CycleM0
rjmp CycleM1
rjmp CycleM2
rjmp CycleM3
rjmp CycleM4
rjmp CycleM5
rjmp CycleM6
rjmp CycleM7
rjmp CycleM8
ret ; voltage only
;
; Mode 0: Measured prescaled frequency, display frequency
;
CycleM0:
clr R5 ; for detecting an overflow in R5
lsl R1 ; * 2
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 4
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 8
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 16
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 32
rol R2
rol R3
rol R4
rol R5
lsl R1 ; * 64
rol R2
rol R3
rol R4
rol R5
tst R5 ; check overflow
breq CycleM0a ; no error
rjmp CycleOvf
CycleM0a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'F'
rjmp DisplMode
;
; Mode 1: Frequency measured, prescale = 1, display frequency
;
CycleM1:
clr rDiv1 ; detect overflow in rDiv1
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
rol rDiv1
tst rDiv1 ; check overflow
breq CycleM1a ; no error
rjmp CycleOvf
CycleM1a:
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'f'
rjmp DisplMode
;
; Mode 2: Time measured, prescale = 1, display frequency
;
CycleM2:
rcall Divide
tst rRes4
brne CycleM2a
rcall DisplFrac
ldi ZL,'v'
rcall DisplMode
ret
CycleM2a:
mov rRes1,rRes2 ; number too big, skip fraction

http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm (2 of 4)1/20/2009 7:59:09 PM


http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm

mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'H'
st X+,rmp
ldi rmp,'z'
st X+,rmp
ldi rmp,' '
st X,rmp
.ENDIF
ldi ZL,'v'
rcall DisplMode
ret
;
; Measure time, display rounds per minute
;
CycleM3:
rcall Divide
clr R0 ; overflow detection
clr rmp
lsl rRes1 ; * 2
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 4
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
mov rDiv1,rRes1 ; copy
mov rDiv2,rRes2
mov rDiv3,rRes3
mov rDiv4,rRes4
lsl rRes1 ; * 8
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 16
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 32
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
lsl rRes1 ; * 64
rol rRes2
rol rRes3
rol rRes4
adc R0,rmp
tst R0 ; overflow?
breq CycleM3a
rjmp CycleOvf
CycleM3a:
sub rRes1,rDiv1
sbc rRes2,rDiv2
sbc rRes3,rDiv3
sbc rRes4,rDiv4
mov rRes1,rRes2
mov rRes2,rRes3
mov rRes3,rRes4
clr rRes4
rcall Displ4Dec
.IF ! cDisplay8
ldi rmp,' '
st X+,rmp
ldi rmp,'r'
st X+,rmp
ldi rmp,'p'
st X+,rmp
ldi rmp,'m'
st X+,rmp
.ENDIF
ldi ZL,'u'
rcall DisplMode
ret
;
; Measure time high+low, display time
;
CycleM4:
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'t'
rcall DisplMode
ret
;
; Measure time high, display time
;
CycleM5:
sbrs rFlg,bEdge
rjmp CycleM5a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'h'
rcall DisplMode
CycleM5a:
ret
;
; Measure time low, display time
;
CycleM6:
sbrc rFlg,bEdge
rjmp CycleM6a
rcall Multiply
rcall Displ4Dec
rcall DisplSec
ldi ZL,'l'
rcall DisplMode
CycleM6a:
ret
;
; Measure time high and low, display pulse width ratio high in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active high time
;
CycleM7:
sbrs rFlg,bEdge
rjmp CycleM7a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rRes1,Z+ ; copy counter value
ld rRes2,Z+
ld rRes3,Z+
ld rRes4,Z+
add rDiv1,rRes1 ; add to total time
adc rDiv2,rRes2
adc rDiv3,rRes3
adc rDiv4,rRes4
brcs CycleM7b
mov rmp,rRes1 ; copy high value to divisor
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM7b ; error
rcall DisplPw ; display the ratio
ldi ZL,'P'
rjmp DisplMode
CycleM7a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM7b: ; overflow
ldi rmp,'P'
rjmp PulseOvFlw
;
; Measure time high and low, display pulse width ratio low in %
; if the edge was negative, store the measured time, if positive calculate
; rRes and rDiv hold the active low time, sCtr the last active high time
; to CalcPw: rDelH:rDelL:R0:rmp = active low time
;
CycleM8:
sbrs rFlg,bEdge
rjmp CycleM8a
ldi ZH,HIGH(sCtr) ; edge is high, calculate
ldi ZL,LOW(sCtr)
ld rmp,Z+ ; read high-time
ld R0,Z+
ld rDelL,Z+
ld rDelH,Z
add rDiv1,rmp ; add to total time
adc rDiv2,R0
adc rDiv3,rDelL
adc rDiv4,rDelH
mov rmp,rRes1 ; copy the active low time
mov R0,rRes2
mov rDelL,rRes3
mov rDelH,rRes4
rcall CalcPw ; calculate the ratio
brcs CycleM8b ; error
rcall DisplPw ; display the ratio
ldi ZL,'p'
rjmp DisplMode
CycleM8a:
ldi ZH,HIGH(sCtr)
ldi ZL,LOW(sCtr)
st Z+,rRes1 ; copy counter value
st Z+,rRes2
st Z+,rRes3
st Z+,rRes4
ret
CycleM8b: ; overflow
ldi rmp,'p'
rjmp PulseOvFlw
;
; Converts an ADC value in R1:R0 to a voltage for display
; cAdc2U input: ADC value, output: Voltage in V for display
;
cAdc2U:
clr R2 ; clear the registers for left shift in R3:R2
clr R3
ldi rmp,HIGH(cMultiplier) ; Multiplier to R5:R4
mov R5,rmp
ldi rmp,LOW(cMultiplier)
mov R4,rmp
clr XL ; clear result in ZH:ZL:XH:XL
clr XH
clr ZL
clr ZH
cAdc2U1:
lsr R5 ; shift Multiplier right
ror R4
brcc cAdc2U2 ; bit is zero, don't add
add XL,R0 ; add to result
adc XH,R1
adc ZL,R2
adc ZH,R3
cAdc2U2:
mov rmp,R4 ; check zero
or rmp,R5
breq cAdc2U3 ; end of multiplication
lsl R0 ; multiply by 2
rol R1
rol R2
rol R3
rjmp cAdc2U1 ; go on multipying
cAdc2U3:
ldi rmp,$80 ; round up
add XL,rmp
ldi rmp,$00
adc XH,rmp
adc ZL,rmp
adc ZH,rmp
tst ZH ; check overflow
mov R1,XH ; copy result to R2:R1
mov R2,ZL
ldi XH,HIGH(sResult+16) ; point to result
ldi XL,LOW(sResult+16)
ldi rmp,'U'
st X+,rmp
breq cAdc2U5
ldi ZH,HIGH(2*AdcErrTxt)
ldi ZL,LOW(2*AdcErrTxt)
cAdc2U4:
lpm
tst R0
breq cAdc2U6
sbiw ZL,1
st X+,R0
rjmp cAdc2U4
cAdc2U5:
clr R0
ldi ZH,HIGH(10000)
ldi ZL,LOW(10000)
rcall DecConv
inc R0
ldi ZH,HIGH(1000)
ldi ZL,LOW(1000)
rcall DecConv
ldi rmp,cDecSep
st X+,rmp
clr ZH
ldi ZL,100
rcall DecConv
ldi ZL,10
rcall DecConv
ldi rmp,'0'
add rmp,R1
st X+,rmp
ldi rmp,'V'
st X,rmp
lds rmp,sResult+17
cpi rmp,' '
brne cAdc2U6
ldi rmp,'='
sts sResult+17,rmp
cAdc2U6:
ret
;
AdcErrTxt:
.DB "overflw",$00
;
; ===========================================
; Lcd display routines
; ===========================================
;
.IF cDisplay ; if display connected
;
; LcdE pulses the E output for at least 1 us
;
LcdE:
sbi PORTB,bLcdE
.IF cFreq>14000000
nop
nop
.ENDIF
.IF cFreq>12000000
nop
nop
.ENDIF
.IF cFreq>10000000
nop
nop
.ENDIF
.IF cFreq>8000000
nop
nop
.ENDIF
.IF cFreq>6000000
nop
nop
.ENDIF
.IF cFreq>4000000
nop
nop
.ENDIF
.IF cFreq>2000000
nop
nop
.ENDIF
nop
nop
cbi PORTB,bLcdE
ret
;
; outputs the content of rmp (temporary
; 8-Bit-Interface during startup)
;
LcdRs8:
out PORTB,rmp
rcall LcdE
ret
;
; write rmp as 4-bit-command to the LCD
;
LcdRs4:
mov R0,rmp ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original back
andi rmp,0x0F ; clear upper nibble
out PORTB,rmp ; write to display interface
rcall LcdE
mov rmp,R0 ; restore rmp
ret
;
; write rmp as data over 4-bit-interface to the LCD
;
LcdData4:
push rmp ; save rmp
mov rmp,R0 ; copy rmp
swap rmp ; upper nibble to lower nibble
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE ; pulse E
mov rmp,R0 ; copy original again
andi rmp,0x0F ; clear upper nibble
sbr rmp,1<<bLcdRs ; set Rs to one
out PORTB,rmp ; write to display interface
rcall LcdE
rcall Delay40us
pop rmp ; restore rmp
ret
;
; writes the text in flash to the LCD, number of
; characters in rmp
;
LcdText:
lpm ; read character from flash
adiw ZL,1
rcall LcdData4 ; write to
rcall delay40us
dec rmp
brne LcdText
ret
;
; Inits the LCD with a 4-bit-interface
;
LcdInit:
ldi rmp,0x0F | (1<<bLcdE) | (1<<bLcdRs)
out DDRB,rmp
clr rmp
out PORTB,rmp
rcall delay15ms ; wait for complete self-init
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay4_1ms ; wait for 4.1 ms
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay100us ; wait for 100 us
ldi rmp,0x03 ; Function set 8-bit interface
rcall LcdRs8
rcall delay40us ; delay 40 us
ldi rmp,0x02 ; Function set 4-bit-interface
rcall LcdRs8
rcall delay40us
.IF cDisplay2
ldi rmp,0x28 ; 4-bit-interface, two line display
.ELSE
ldi rmp,0x20 ; 4-bit-interface, single line display
.ENDIF
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x08 ; display off
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x01 ; display clear
rcall LcdRs4
rcall delay1_64ms ; delay 1.64 ms
ldi rmp,0x06 ; increment, don't shift
rcall LcdRs4
rcall delay40us ; delay 40 us
ldi rmp,0x0C ; display on
rcall LcdRs4
rcall delay40us
ldi rmp,0x80 ; position on line 1
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
ldi ZH,HIGH(2*LcdInitTxt8)
ldi ZL,LOW(2*LcdInitTxt8)
.ELSE
ldi rmp,16
ldi ZH,HIGH(2*LcdInitTxt16)
ldi ZL,LOW(2*LcdInitTxt16)
.ENDIF
rcall LcdText
.IF cDisplay2
ldi rmp,0xC0 ; line 2
rcall LcdRs4
rcall delay40us ; delay 40 us
.IF cDisplay8
ldi rmp,8
.ELSE
ldi XH,HIGH(sResult+25)
ldi XL,LOW(sResult+25)
ldi ZH,HIGH(2*LcdInitTxtMode)
ldi ZL,LOW(2*LcdInitTxtMode)
ldi rmp,6
LcdInitMode:
lpm
adiw ZL,1
st X+,R0
dec rmp
brne LcdInitMode
ldi rmp,16
.ENDIF
rcall LcdText
.ENDIF
ret
.IF cDisplay8
LcdInitTxt8:
.DB "F-CNT V1"
.IF cDisplay2
.DB "-DG4FAC-"
.ENDIF
.ELSE
LcdInitTxt16:
.DB "Freq-counter V01"
.IF cDisplay2
.DB " (C)2005 DG4FAC "
LcdInitTxtMode:
.DB " Mode="
.ENDIF
.ENDIF
;
; Display frequency/time on Lcd
;
LcdDisplayFT:
.IF ! cDisplay2 ; single line display
cpi rMode,cModeVoltage ; voltage display selected?
breq LcdDisplayFT2
.ENDIF
ldi rmp,$80 ; set display position to line 1
rcall LcdRs4
rcall Delay40us
ldi ZH,HIGH(sResult) ; point Z to line buffer
ldi ZL,LOW(sResult)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayFT1:
ld R0,Z+ ; read a char
rcall LcdData4 ; display on LCD
dec rmp
brne LcdDisplayFT1
LcdDisplayFT2:
ret
;
; Display voltage on the display
;
LcdDisplayU:
.IF cDisplay2 ; two-line LCD connected
.IF !cDisplay8
lds rmp,sModeNext
subi rmp,-'0'
sts sResult+31,rmp
.ENDIF
ldi rmp,$C0 ; output to line 2
.ELSE
cpi rMode,cModeVoltage ; check switch
brne LcdDisplayU2
ldi rmp,$80 ; output to line 1
.ENDIF
rcall LcdRs4 ; set output position
rcall Delay40us
ldi ZH,HIGH(sResult+16) ; point to result
ldi ZL,LOW(sResult+16)
.IF cDisplay8
ldi rmp,8
.ELSE
ldi rmp,16
.ENDIF
LcdDisplayU1:
ld R0,Z+ ; read character
rcall LcdData4
dec rmp ; next char
brne LcdDisplayU1 ; continue with chars
LcdDisplayU2:
ret
;
.ENDIF ; end LCD routines to be included
;
; ===========================================
; Uart routines
; ===========================================
;
.IF cUart
UartInit: ; Init the Uart on startup
.EQU cUbrr = (cFreq/cBaud/16)-1 ; calculating UBRR single speed
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi rmp,HIGH(cUbrr) ; set URSEL to zero, set baudrate msb
out UBRRH,rmp
ldi rmp,LOW(cUbrr) ; set baudrate lsb
out UBRRL,rmp
ldi rmp,(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0) ; set 8 bit characters
out UCSRC,rmp
ldi rmp,(1<<RXCIE)|(1<<RXEN)|(1<<TXEN) ; enable RX/TX and RX-Ints
out UCSRB,rmp
rcall delay10ms ; delay for 10 ms duration
ldi ZH,HIGH(2*txtUartInit)
ldi ZL,LOW(2*txtUartInit)
rjmp UartSendTxt
;
; Uart receive buffer space in SRAM
; sUartRxBs is buffer start
; sUartRxBe is buffer end
; sUartRxBp is buffer input position
; .EQU UartRxbLen = 38 ; Buffer length in bytes
; sUartFlag: ; flag register for Uart
; .BYTE 1
; .EQU bUMonU = 0 ; displays voltage over Uart
; .EQU bUMonF = 1 ; displays frequency over Uart
; ; free: bits 2..7
; sUartMonUCnt: ; counter for Monitoring voltage
; .BYTE 1
; sUartMonURpt: ; counter preset for monitoring voltage
; .BYTE 1
; sUartRxBp: ; buffer pointer
; .BYTE 1
; sUartRxBs: ; buffer
; .BYTE UartRxbLen
; sUartRxBe: ; buffer end
; .EQU cNul = $00
; .EQU cClrScr = $0C
; .EQU cCr = $0D
; .EQU cLf = $0A
;
UartRxLine:
cbr rFlg,1<<bUartRxLine ; clear line complete flag
ldi rmp,LOW(sUartRxBs) ; set buffer pointer to start
sts sUartRxBp,rmp
ldi ZH,HIGH(UartReturn) ; push return adress to stack
ldi ZL,LOW(UartReturn)
push ZL
push ZH
ldi ZH,HIGH(sUartRxBs) ; set Z to Buffer-Start
ldi ZL,LOW(sUartRxBs)
ld rmp,Z+ ; read first character
cpi rmp,'h' ; help?
brne UartRxLine1
rjmp UartHelp
UartRxLine1:
cpi rmp,'?' ; help?
brne UartRxLine2
rjmp UartHelp
UartRxLine2:
cpi rmp,'U' ; monitor U on
brne UartRxLine3
rcall UartGetPar
sec
rjmp UartMonUSetC
UartRxLine3:
cpi rmp,'u' ; monitor U off
brne UartRxLine4
clc
rjmp UartMonUSetC
UartRxLine4:
cpi rmp,'F' ; monitor F on
brne UartRxLine5
rcall UartGetPar
sec
rjmp UartMonFSetC
UartRxLine5:
cpi rmp,'f' ; monitor f off
brne UartRxLine6
clc
rjmp UartMonFSetC
UartRxLine6:
cpi rmp,'p' ; parameter?
brne UartRxLine7
rjmp UartMonPar
UartRxLine7:
ldi ZH,HIGH(2*txtUartUnknown) ; send unknown command
ldi ZL,LOW(2*txtUartUnknown)
ret
UartHelp:
ldi ZH,HIGH(2*txtUartHelp) ; send help text
ldi ZL,LOW(2*txtUartHelp)
ret
UartMonUSetC:
lds rmp,sUartFlag
brcs UartMonUSetC1
cbr rmp,1<<bUMonU ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOff)
ldi ZL,LOW(2*txtUartUOff)
ret
UartMonUSetC1:
brne UartMonUSetC2
sts sUartMonURpt,R0
sts sUartMonUCnt,R0
UartMonUSetC2:
sbr rmp,1<<bUMonU ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartUOn)
ldi ZL,LOW(2*txtUartUOn)
ret
UartMonFSetC:
lds rmp,sUartFlag
brcs UartMonFSetC1
cbr rmp,1<<bUMonF ; clear flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOff)
ldi ZL,LOW(2*txtUartFOff)
ret
UartMonFSetC1:
brne UartMonFSetC2
sts sUartMonFRpt,R0
sts sUartMonFCnt,R0
UartMonFSetC2:
sbr rmp,1<<bUMonF ; set flag
sts sUartFlag,rmp
ldi ZH,HIGH(2*txtUartFOn)
ldi ZL,LOW(2*txtUartFOn)
ret
UartMonPar:
ldi ZH,HIGH(2*txtUartNul)
ldi ZL,LOW(2*txtUartNul);
ldi rmp,'U'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonURpt
rcall UartHexR
ldi rmp,','
rcall UartSendChar
ldi rmp,' '
rcall UartSendChar
ldi rmp,'F'
rcall UartSendChar
ldi rmp,'='
rcall UartSendChar
ldi rmp,'$'
rcall UartSendChar
lds rmp,sUartMonFRpt
rjmp UartHexR
;
; Get Parameter from line
;
UartGetPar:
clr R0 ; result register
ld rmp,Z+ ; read char
cpi rmp,cCr ; carriage return
breq UartGetParNoPar
cpi rmp,cLf ; line feed
breq UartGetParNoPar
cpi rmp,'=' ;
brne UartGetParErr
UartGetPar1:
ld rmp,Z+ ; read next char
cpi rmp,cCr ; carriage return?
breq UartGetPar2
cpi rmp,cLf ; line feed?
breq UartGetPar2
subi rmp,'0' ; subtract 0
brcs UartGetParErr
cpi rmp,10 ; larger than 9?
brcc UartGetParErr
mov rir,R0 ; copy to rir
lsl R0 ; * 2
brcs UartGetParErr
lsl R0 ; * 4
brcs UartGetParErr
add R0,rir ; * 5
brcs UartGetParErr
lsl R0 ; * 10
brcs UartGetParErr
add R0,rmp ; add new decimal
brcs UartGetParErr
rjmp UartGetPar1
UartGetPar2:
sez
ret
UartGetParErr:
ldi ZH,HIGH(2*txtUartErr)
ldi ZL,LOW(2*txtUartErr)
rcall UartSendTxt
UartGetParNoPar:
clz ; No parameter set
ret
;
; Hex output over Uart, for debugging
;
UartHexR:
push rmp
swap rmp
rcall UartHexN
pop rmp
UartHexN:
andi rmp,0x0F
subi rmp,-'0'
cpi rmp,'9'+1
brcs UartHexN1
subi rmp,-7
UartHexN1:
rjmp UartSendChar
ret
;
; Return from Uart-Routines, displays text in Z
;
UartReturn:
rcall UartSendTxt ; send text in Z
ldi ZH,HIGH(2*txtUartCursor)
ldi ZL,LOW(2*txtUartCursor)
rjmp UartSendTxt
;
; Send character in rmp over Uart
;
UartSendChar:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartSendChar
out UDR,rmp
ret
;
; Monitoring the voltage over the Uart
;
UartMonU:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonU ; displays voltage over Uart
ret
lds rmp,sUartMonUCnt ; read counter
dec rmp
sts sUartMonUCnt,rmp
brne UartMonU2
lds rmp,sUartMonURpt
sts sUartMonUCnt,rmp
ldi ZH,HIGH(sResult+16)
ldi ZL,LOW(sResult+16)
ldi rmp,8
UartMonU1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonU1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonU1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonU2:
ret
;
; Monitor frequency over UART
;
UartMonF:
lds rmp,sUartFlag ; flag register for Uart
sbrs rmp,bUMonF ; displays frequency over Uart
ret
lds rmp,sUartMonFCnt ; read counter
dec rmp
sts sUartMonFCnt,rmp
brne UartMonF2
lds rmp,sUartMonFRpt
sts sUartMonFCnt,rmp
ldi ZH,HIGH(sResult)
ldi ZL,LOW(sResult)
ldi rmp,16
UartMonF1:
sbis UCSRA,UDRE ; wait for empty buffer
rjmp UartMonF1
ld R0,Z+
out UDR,R0
dec rmp
brne UartMonF1
ldi rmp,cCr
rcall UartSendChar
ldi rmp,cLf
rjmp UartSendChar
UartMonF2:
ret
;
; Send text from flash to UART, null byte ends transmit
;
UartSendTxt:
lpm ; read character from flash
adiw ZL,1
tst R0 ; check end of text
breq UartSendTxtRet
UartSendTxtWait:
sbis UCSRA,UDRE ; wait for empty char
rjmp UartSendTxtWait
out UDR,R0 ; send char
rjmp UartSendTxt
UartSendTxtRet:
ret
;
; Uart text constants
;
txtUartInit:
.DB " ",cClrScr
.DB "************************************************* ",cCr,cLf
.DB "* Frequency- and voltmeter (C)2005 by g.schmidt * ",cCr,cLf
.DB "************************************************* ",cCr,cLf
txtUartMenue:
.DB cCr,cLf,"Commands: <h>elp",cCr,cLf
txtUartCursor:
.DB cCr,cLf,"i> ",cNul

http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm (3 of 4)1/20/2009 7:59:09 PM


http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm

txtUartUnknown:
.DB cCr,cLf,"Unknown command!",cNul,cNul
txtUartUOff:
.DB "Voltage monitoring is off.",cNul,cNul
txtUartUOn:
.DB "Voltage monitoring is on. ",cNul,cNul
txtUartFOff:
.DB "Frequency monitoring is off.",cNul,cNul
txtUartFOn:
.DB "Frequency monitoring is on. ",cNul,cNul
txtUartErr:
.DB "Error in parameter! ",cNul,cNul
txtUartHelp:
.DB cCr,cLf,"Help: ",cCr,cLf
.DB "U[=N](on) or u(Off): monitor voltage output, N=1..255,",cCr,cLf
.DB "F[=N](On) or f(Off): monitor frequency output N=1..255, ",cCr,cLf
.DB "p: display monitoring parameters, ",cCr,cLf
.DB "h or ?: this text."
txtUartNul:
.DB cNul,cNul
.ENDIF
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_en/fcount/fcountV03.asm (4 of 4)1/20/2009 7:59:09 PM


http://www.avr-asm-tutorial.net/avr_en/fcount/ReadMe.txt

******************************************************
* Applying the frequency counter v0.3 as of 9.1.2009 *
******************************************************

Chapters:
---------
1. Adjustments prior to assembling
2. During programming
3. Measuring modes
3.1 Measuring modes
3.2 Displaying measuring modes
4. Display versions
4.1 Display on 2-line-LCDs
4.2 Display on a single-line-LCD
4.3 Display on 16-/20-character-displays
4.4 Display 8-character-displays
5. Display on the serial interface
5.1 Commands on the serial interface
5.2 Format of voltage- and frequency output

1. Adjustments prior to assembling


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

The following adjustments have to be made prior to


assembling the source code in the file fcountV03.asm:

- The switches debug and debugpulse must be set to 0.

- If an LCD is attached, cDisplay must be set to 1,


otherwise to 0.

- If the attached LCD has 8 characters per line,


cDisplay8 must be set to 1. If a 16- or 20-
character-per-line-display is used, cDisplay8
must be set to 0.

- If the attached LCD can only display a single line,


cDisplay2 must be set to 0. If two or more lines
can be displayed, cDisplay2 must be set to 1.

- If the serial interface is attached, cUart must be


set to 1. If no serial interface is attached or
serial interfacing is not wanted, set cUart to 0.

- If the prescaler by 16 is attached to another port


bit as PC5, specify pPresc and pPrescD as well as
bPresc accordingly.

- If the processor clock is driven different than at


16 MHz, this frequency has to be written to cFreq.

- If the serial interface should work at a baudrate


different than with 9600 Bd, cBaud has to be
adjusted accordingly.

- If the hardware prescaler for measuring voltages


is different than with the two resistors of 1M,
the two values in cR1 and cR2 have to be changed
accordingly. If the displayed voltages are dif-
ferent from the applied voltages, adjust cRin:
smaller values for cRin yield a higher voltage
on the display, larger values a lower voltage.

2. During programming
---------------------

- The fuses "Ext.Crystal/Resonator HighFreq.; Start-up


time: 16K CK + 64 ms "CKSEL=1111 SUT=11]" and CKOPT
must be set, all other internal and external clock
fuses must be cleared. The screenshots show the
fuses (FusesPony.gif, FusesStudio1.gif and
FusesStudio2.gif).

3. Measuring modes
------------------

3.1 Measuring modes

The measuring mode is selected with the voltage divider


or variable resistor. Following modes can be selected:
0: Measuring frequency with prescaler, gate time 0,25 s,
result in Hz
1: Measuring frequency without prescaler, gate time 0,25 s,
result in Hz
2: Measuring frequency as period measurement with calcu-
lation to frequency, result as 0.01 Hz reswp. 0.001 Hz
3: Rounds-per-Minute measurement, without prescaler, via
period measurement with conversion to RPM, result in
rpm
4: Period length of complete cycle, result in microseconds
5: Period length of high-period, result in microseconds
6: Period length of low-period, result in microseconds
7: Period portion of high-period, result in 0,1%
8: Period portion of low-period, result in 0,1%
9: Voltage measuring only, result in 0,001 Volts
Selection of mode Modus 9 (potentiometer to the right)
switches frequency/time/period measurement off.

3.2 Displaying measuring modes

The measuring mode is displayed on the beginning of


the first LCD line with a letter and an equal sign
(format "X="). With an 8-character-LCD attached,
these two characters are displayed only if the
result of the measurement is small enough and allows
this.

During display, the following abbreviations for the


mode are used:
- "F=": Frequency in Hz, measured with prescaler,
resolution +/- 32 Hz
- "f=": Frequency in Hz, measured withput prescaler,
resolution +/- 4 Hz
- "v=": Frequency in Hz with smaller decimals, measured
via time, resolution +/- 0,01 Hz
- "u=": Rounds per minute, measured via time, resolution
+/- 1 Upm
- "t=": Cycle duration in mikrosekunden, resolution
+/- 1 microseconds
- "h=": Duration of a high-period, resolution
+/- 1 microseconds
- "l=": Duration of a low-period, resolution
+/- 1 microseconds
- "P=": Period portion of a high-period in %,
resolution +/- 0,1%
- "p=": Period portion of a low-period in %,
resolution +/- 0,1%
- "U=": Voltage on the input, resolution depends from the
resistor pair on the input, at (1M + 1M) approx.
4 millivolts.

4. Display versions
-------------------

The update of the LCD is depending from the mode: in


frequency measuring modes the interval is 0.25 seconds,
in period measurements it is depending from the
duration of measuring period.

4.1 Display on 2-line-LCDs

Depending from the selected mode, the first LCD line


displays the frequency, the time or the period portion.
The second line displays the measured voltage.
With a double line LCD with more than 8 characters per
line, the measuring mode (0..9) is displayed at the end
of the second line.

4.2 Display on a single-line-LCD

In modes 0..8 the LCD shows the results of frequency,


time or period portion measurements. In mode 9, the
voltage is displayed.

4.3 Display on 16-/20-character-displays

The display is complete, with mode, thousands and


decimal separators as well as the dimension.
Mode Format
-----------------------
0 "F=99,999,999 Hz "
1 "f= 9,999,999 Hz "
2 "v= 9,999.999 Hz "
3 "u= 9,999,999 rpm"
4 "t=99,999,999 us "
5 "h=99,999,999 us "
6 "l=99,999,999 us "
7 "P=100,0% "
8 "p=100,0% "
9 "U=9,999V "

4.4 Display with 8-character-displays

Period portions and voltages are displayed complete.


Display in other modes are shortened. Suppressed
are:
- the output of thousands separarors,
- the output of the dimension,
- if required, the equal-sign and the character for
mode recognition.
The output displays
- frequencies in Hz
- rps as rpm
- times in microseconds.

Mode Format short Format long


----------------------------
0 "F=999999" "99999999"
1 "f=999999" "99999999"
2 "v=999999" "99999999"
3 "u=999999" "99999999"
4 "t=999999" "99999999"
5 "h=999999" "99999999"
6 "l=999999" "99999999"
7 "P=100,0%" "P=100,0%"
8 "p=100,0%" "p=100,0%"
9 "U=9,999V" "U=9,999V"

5. Display on the serial interface


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

The serial interface sends the following text after


a reset:

*************************************************
* Frequency- and voltmeter (C)2005 by g.schmidt *
*************************************************

Commands: <h>elp

i>

5.1 Commands on the serial interface

The following commands are implementiert:

u : Output voltage off


U : Output voltage on
U=123 : Interval for voltage output 123 cycles
f : Output frequency off
F : Output frequency on
F=123 : Interval for frequency output 123 cycles
p : Output the currently selected intervals
h, ? : Output help information

5.2 Format of voltage- and frequency output

The output of voltages ins in the format


"U=4,958V<CR><LF>"
The output of frequencies is depending from the selected
mode, e.g. in mode 0:
"F=1.234.567 Hz<CR><LF>"

http://www.avr-asm-tutorial.net/avr_en/fcount/ReadMe.txt1/20/2009 7:59:14 PM
http://www.avr-asm-tutorial.net/avr_en/fcount/scheme_v03.gif

http://www.avr-asm-tutorial.net/avr_en/fcount/scheme_v03.gif1/20/2009 7:59:15 PM
Gift project: AVR-Egg-timer

Path: Home => AVR overview => Applications => Egg-timer => Assembler source code

The ATtiny2313V-Egg-Timer - Assembler source


code

; *****************************************************
; * ATtiny2313-Eggwatch, Version 1, 20.10.2006 *
; * (C)2006 by G.Schmidt info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "tn2313def.inc"
.LIST
;
; ***************************************
; Fuses-setting in the ATtiny2313V
; ***************************************
;
; - Interal RC-Oscillator to 4 Mcs/s, CLKSEL3:0 = 0010, SUT1:0 =
10
; - Internal Clock prescaler to 8, CKDIV8 = Enabled
;
; ***************************************
; Hardware - scheme
; ***************************************
;
; __________
; / |_| |
; +3V O--|Res VCC|--O +3V
; | |
; L1K O--|PD0 PB7|--O L10A
; | |
;L1A/L2K O--|PD1 PB6|--O L9A/L10K
; | AT |
; O--|PA1 PB5|--O L8A/L9K
; | tiny |
; O--|PA0 PB4|--O L7A/L8K
; | 2313 |
;L2A/L3K O--|PD2 PB3|--O
; | V |
;L4K/L3A O--|PD3 PB2|--||--O Lsp
; | (OC0A)|
;L5K/L4A O--|PD4 PB1|--O
; | |
;L6K/L5A O--|PD5 PB0|--O L0K
; | |
; GND O--|GND PD6|--O L6A/L7K
; |___________|
;
;
; ***************************************
; Define Ports and Portbits
; ***************************************
;
.EQU pOcO = PORTB
.EQU dOcO = DDRB
.EQU bOcO = 2
;
.EQU pL0K = PORTB
.EQU dL0K = DDRB
.EQU bL0K = 0
;
.EQU pL1K = PORTD
.EQU dL1K = DDRD
.EQU bL1K = 0
;
.EQU pL1A = PORTD
.EQU dL1A = DDRD
.EQU bL1A = 1
;
.EQU pL2K = PORTD
.EQU dL2K = DDRD
.EQU bL2K = 1
;
.EQU pL2A = PORTD
.EQU dL2A = DDRD
.EQU bL2A = 2
;
.EQU pL3K = PORTD
.EQU dL3K = DDRD
.EQU bL3K = 2
;
.EQU pL3A = PORTD
.EQU dL3A = DDRD
.EQU bL3A = 3
;
.EQU pL4K = PORTD
.EQU dL4K = DDRD
.EQU bL4K = 3
;
.EQU pL4A = PORTD
.EQU dL4A = DDRD
.EQU bL4A = 4
;
.EQU pL5K = PORTD
.EQU dL5K = DDRD
.EQU bL5K = 4
;
.EQU pL5A = PORTD
.EQU dL5A = DDRD
.EQU bL5A = 5
;
.EQU pL6K = PORTD
.EQU dL6K = DDRD
.EQU bL6K = 5
;
.EQU pL6A = PORTD
.EQU dL6A = DDRD
.EQU bL6A = 6
;
.EQU pL7K = PORTD
.EQU dL7K = DDRD
.EQU bL7K = 6
;
.EQU pL7A = PORTB
.EQU dL7A = DDRB
.EQU bL7A = 4
;
.EQU pL8K = PORTB
.EQU dL8K = DDRB
.EQU bL8K = 4
;
.EQU pL8A = PORTB
.EQU dL8A = DDRB
.EQU bL8A = 5
;
.EQU pL9K = PORTB
.EQU dL9K = DDRB
.EQU bL9K = 5
;
.EQU pL9A = PORTB
.EQU dL9A = DDRB
.EQU bL9A = 6
;
.EQU pL10K = PORTB
.EQU dL10K = DDRB
.EQU bL10K = 6
;
.EQU pL10A = PORTB
.EQU dL10A = DDRB
.EQU bL10A = 7
;
; ***************************************
; Function of Timing
; ***************************************
;
; Timer1 = time measuring
; _______ ______ ______ ______ _____ ______
; |RC-Osc.| | CDiv |500|Presc.|62,5|TC1CNT|5cs| LED |0,5|MinCnt|
; | 4 Mcs |===>| / 8 |==>| / 8 |===>|/12500|==>|Count|==>| / 30 |
==>1 Min.
; |_______| |______|kcs|______|kcs |______| |_____|cs |______|
; |
; Timer0= Audio-gener. |
; | ______ ______
; | |Presc.| |TC0CNT|992cs/s
; |=>| / 8 |==>| / 63 |===> OC0A = Beep-
Loudspeaker
; |______| |______|
;
;
; ***************************************
; Register
; ***************************************
;
.DEF rmp = R16
.DEF rFlg = R17
.DEF rLed = R18
.DEF rSec = R19
.DEF rMin = R20
.DEF rNb = R21
;
; ***************************************
; Reset and Interrupt-Vectors
; ***************************************
;
.CSEG
.ORG $0000
rjmp Main ; Reset
reti ; INT0 Interrupt
reti ; INT1 Interrupt
reti ; TC1Capt Interrupt
rjmp TC1CmpA ; Timer 1 Compare A match
reti ; TC1 Overflow Int
reti ; TC0 Overflow Int
reti ; UART0 RX Int
reti ; UART0 TX Int
reti ; Ana Comp Int
reti ; PCINT
reti ; TC1 CompB Int
reti ; TC0 Compare Match A Int
reti ; TC0 Compare Match B Int
reti ; USISTART Int
reti ; USIOverflow Int
reti ; EERDY Int
reti ; WDT Overflow Int
;
; ***************************************
; TC1 Compare Match A Interrupt Routine
; ***************************************
;
TC1CmpA:
set
reti
;
; ***************************************
; Main program
; ***************************************
;
Main:
; Stack init
ldi rmp,LOW(RAMEND) ; Set Stack pointer
out SPL,rmp
; Init Register
ldi rFlg,0 ; Init Flag
ldi rLed,0 ; Init LEDs
ldi rSec,0 ; Init 0.5-Second counter
ldi rMin,1 ; Init Minute counter
ldi rNb,1 ; Init Beep-counter
; Init OCR0A-Output for Beep
sbi dOcO,bOcO
; Init Timer 1 for time measuring and LED control
ldi rmp,HIGH(12500) ; CTC-value
out OCR1AH,rmp
ldi rmp,LOW(12500)
out OCR1AL,rmp
clr rmp ; Controlword A
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; to CTC mode
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; Timer1-Interrupt
out TIMSK,rmp
; Init Timer 0 for Beep-Output
ldi rmp,(1<<COM0A0)|(1<<WGM01) ; CTC, Toggle Compare A
out TCCR0A,rmp
ldi rmp,1<<CS01 ; beep on
out TCCR0B,rmp
ldi rmp,63 ; CTC-value
out OCR0A,rmp
ldi rmp,1<<SE ; sleep idle
out MCUCR,rmp
sei ; Enable Ints
;
; ***************************************
; Main program - Loop
; ***************************************
;
; to sleep mode idle
An:
sleep ; Sleep on
nop ; wake up
brtc An ; T-Flag not activated by Timer
clt ; T-Flag reset
sbrc rLed,0 ; Bit 0 is Beep-control
rjmp BeepAus
tst rNb ; test beeps = 0
breq BeepAus ; switch Beeps off
ldi rmp,1<<CS01 ; beep on
out TCCR0B,rmp
dec rNb ; decrement Beeps
rjmp LedAus
BeepAus:
ldi rmp,0 ; Beep off, stop Timer
out TCCR0B,rmp
LedAus:
ldi ZH,HIGH(TabAus) ; jump table LED off
ldi ZL,LOW(TabAus)
add ZL,rLed ; add current LED
brcc MachAus
inc ZH
MachAus:
ijmp ; current LED deactivation
Aus: ; LED is off
inc rLed ; increase conter
cpi rLed,10 ; already at ten
brne Weiter ; no
clr rLed ; yes, start again
inc rSec ; inc 0.5-second counter
cpi rSec,30 ; reached 30?
brcs Weiter ; no, not yet
clr rSec ; yes, clear 0.5-second counter
mov rNb,rMin ; copy Minutes to Beep-counter
inc rMin ; inc Minute counter
cpi rMin,11 ; 10 Minutes over?
brcs Weiter ; no
clr rMin ; restart Minute counter
ldi rNb,255 ; Beep for a whole Minute
sbi dL0K,bL0K ; Output yellow LED on
cbi pL0K,bL0K ; yellow LED on
Weiter: ; current LED red or green?
ldi ZH,HIGH(TabRot) ; try with red
ldi ZL,LOW(TabRot)
cp rLed,rMin ; current LED smaller than Minute counter
brcs Weiter1 ; yes
ldi ZH,HIGH(TabGruen) ; no, it's green
ldi ZL,LOW(TabGruen)
Weiter1: ; switch LED on
add ZL,rLed ; add LED to base address
brcc MachAn
inc ZH
MachAn: ; switch LED on
ijmp
;
; ***************************************
; Jump tables
; ***************************************
;
; Jump table for LEDs red
TabRot:
rjmp L1R
rjmp L2R
rjmp L3R
rjmp L4R
rjmp L5R
rjmp L6R
rjmp L7R
rjmp L8R
rjmp L9R
rjmp L10R
; Jump table for LEDs green
TabGruen:
rjmp L1G
rjmp L2G
rjmp L3G
rjmp L4G
rjmp L5G
rjmp L6G
rjmp L7G
rjmp L8G
rjmp L9G
rjmp L10G
; Jump table for LEDs off
TabAus:
rjmp L1A
rjmp L2A
rjmp L3A
rjmp L4A
rjmp L5A
rjmp L6A
rjmp L7A
rjmp L8A
rjmp L9A
rjmp L10A
;
; ***************************************
; LED switching routines
; ***************************************
;
; LEDs off
L1A:
cbi pL1A,bL1A
cbi pL1K,bL1K
cbi dL1A,bL1A
cbi dL1K,bL1K
rjmp Aus
L2A:
cbi pL2A,bL2A
cbi pL2K,bL2K
cbi dL2A,bL2A
cbi dL2K,bL2K
rjmp Aus
L3A:
cbi pL3A,bL3A
cbi pL3K,bL3K
cbi dL3A,bL3A
cbi dL3K,bL3K
rjmp Aus
L4A:
cbi pL4A,bL4A
cbi pL4K,bL4K
cbi dL4A,bL4A
cbi dL4K,bL4K
rjmp Aus
L5A:
cbi pL5A,bL5A
cbi pL5K,bL5K
cbi dL5A,bL5A
cbi dL5K,bL5K
rjmp Aus
L6A:
cbi pL6A,bL6A
cbi pL6K,bL6K
cbi dL6A,bL6A
cbi dL6K,bL6K
rjmp Aus
L7A:
cbi pL7A,bL7A
cbi pL7K,bL7K
cbi dL7A,bL7A
cbi dL7K,bL7K
rjmp Aus
L8A:
cbi pL8A,bL8A
cbi pL8K,bL8K
cbi dL8A,bL8A
cbi dL8K,bL8K
rjmp Aus
L9A:
cbi pL9A,bL9A
cbi pL9K,bL9K
cbi dL9A,bL9A
cbi dL9K,bL9K
rjmp Aus
L10A:
cbi pL10A,bL10A
cbi pL10K,bL10K
cbi dL10A,bL10A
cbi dL10K,bL10K
rjmp Aus
; LEDs green
L1G:
sbi pL1A,bL1A
cbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2G:
sbi pL2A,bL2A
cbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3G:
sbi pL3A,bL3A
cbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4G:
sbi pL4A,bL4A
cbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5G:
sbi pL5A,bL5A
cbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6G:
sbi pL6A,bL6A
cbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7G:
sbi pL7A,bL7A
cbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8G:
sbi pL8A,bL8A
cbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9G:
sbi pL9A,bL9A
cbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10G:
sbi pL10A,bL10A
cbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
; LEDs red
L1R:
cbi pL1A,bL1A
sbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2R:
cbi pL2A,bL2A
sbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3R:
cbi pL3A,bL3A
sbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4R:
cbi pL4A,bL4A
sbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5R:
cbi pL5A,bL5A
sbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6R:
cbi pL6A,bL6A
sbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7R:
cbi pL7A,bL7A
sbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8R:
cbi pL8A,bL8A
sbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9R:
cbi pL9A,bL9A
sbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10R:
cbi pL10A,bL10A
sbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
;
; End of source code
;

To the top of page

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/eggtimer/eggtimer_asm.html1/20/2009 7:59:22 PM
Gift project: AVR-Egg-timer

Pfad: Home => AVR overview => applications => Egg-timer

A small homemade project - just for fun - but very practical

The ATtiny2313V-egg-timer
1. Description
2. Hardware
3. Functioning

1. Description
Who didn't already run into that: the n-th birthday celebration of friend X.Y. is coming up, and you do not
have any idee what your friend's household is missing. Now, you can just go to a shop, that sells any kind
of presents, and buy something sense- and useless, wrap it in nice paper, and just hope that no one else will
have the same (non-)idea. Otherwise the main question will come up: exchange this piece to another piece,
that no one needs?

If you are experienced in soldering some electronic parts together and of programming an AVR, you have a
clear avantage over all your other friends: producing a very individual gift, that no one can copy by chance,
and put it on the birthday gift table. During the next twelve monthes, all our friends, relatives and
neighbours receive an up-to-date, individually designed and personally flavoured egg-timer. Of course,
equipped with the latest, greatest micro-professor, as available on the electronic device scene today. Not
just one of the old-fashioned and traditional flasks, filled with acid-cleaned silica sand. Quietly rippling
sand was yesterday, today it is beeping and blinking.

The principle is very easy: a row of LEDs, e.g. placed like a bar, is lit green and red (first variation: yellow
and red), whenever a minute is over, one more green light changes from green to red. To save battery
capacity and use the timer for more than one egg to cook, only one LED is lit at a time in the display cycle.
The band is running fast, so that there is some action in the kitchen and you can catch the timer's state in
just a short glimpse, looking up from your morning newspaper.

If you are too fascinated by all the news in your newspaper, you do NOT even need to keep an eye on your
timer: it just beeps the number of elapsed minutes. That makes your egg-timer also compatible with the
needs of handicapped people, that arent able to see the disco lights, which makes a major difference to the
sand-filled equipment. If ten minutes are over, a yellow light and a continous beep tells you, that the egg
yolk has turned to green now, and that the egg can be thrown into the trashcan.

I only describe the electronic and software design here, so you must add your own creativity in the package
design. For placing the LEDs, consider the following opportunities:

1. A straight line of LEDs signals geometric strength, and is more adapted to straight-thinking people
like e.g. mathmaticians or housekeepers, model "straight forward",
2. A circle is possible, and more adapted to people with a similiar belly, model "beercan",
3. For the more playful people, the form of an egg is more appropriate. This model is also good for the
short-memoried, because it reminds what the equipment is made for, model "short-term memory",
4. For the more chaotic, untidiness- and complexity-loving neighbor, you can place the LEDs in a
random manner on the unregular-shaped casing, model "Hundertwasser" (see an intro to
Hundertwasser),
5. The design for the gamer: place the LEDs randomly, and exchange the LEDs every minute randomly
by software. He will love to guess where the next LED will get red, model "vote&surprise".

From my own experience it has been proven top, to add an individually designed instruction manual to that
gift. Humorous formulations, like english words combined with taiwanese grammar, bring good vibes to the
birthday celebration. Also, you can write the instruction in english, translate this to japanese language,
retranslate it with Babelfish to english, and then exchange single words by their dutch translation.

To the top of page

2. Hardware
Th

hardware scheme is pretty easy: the two batteries (2*AA, 2*AAA is suitable, too) supply the hardware with
3 wonderful Volts. More voltage destroys the LEDs very fast, so don't supply with 5 Volts. The row of dual-
LEDs is cascated with resistors, limiting the currents. Each LED can be driven in both ways by the portpins.
When soldering the LEDs, only ensure their uniform direction, their colour can be easily changed by
software.

All portpins that are not needed to drive a certain single LED, are set to tristate (input) and therefore do not
interfere. The ATtiny2313V (without V is also fine) always drives only one LED, the voltage drop, when
sourcing from the pin under load, has been calculated in the design of the resistor. The yellow egg-throw
LED has its own portpin. A small piezo-speaker is directly pinned to the OC0A output. If you don't have a
piezo, you can use a small 32-Ohm-speaker, decoupled with a C of 100 µF.

To the top of page

3. Functions

3.1 Processor programming

The processor hardware cannot be programmed in in-system-


mode (ISP), because the operating voltage should not exceed
3 V. The processor has to be prgrammed on an extra
programming board and then moved to the egg-timer hardware.

First, the processor is changed to operate with the internal 4-Mcs/


s-RC-oscillator, to reduce power consumption. The DIV8 fuse
stays activated, so that the processor runs with a 500 kcs/s
clock. Slow enough for the V-version.

Assembler source code for the basic version is for download in


asm format here and can be viewed in HTML format here.

In the source code, first the portpins are assigned. That means
that all LEDs can be mounted in any sequence and assigned
here. The drive row must be assigned by the correct output port,
portpin and direction port. The extensive program code to drive
the correct LED, at the end of the source code, is attributed to
that flexibility in placing the LEDs.

Time measurement and LED-switching is assigned task of the 16-


bit-timer 1, that runs in CTC mode. When reaching the value in
the compare register A, every 0.2 sec, an interrupt is triggered
and the T flag in the status register is set. The interrupt wakes up
the processor from idle sleep. The T flag is cleared, and the
lowest bit of the LED counter is checked. If this is one, the beep
tone is switched off. If it is zero, it is checked whether a beep
tone has to be generated. If yes, the speaker output is turned on
(Timer 0 is activated) and the number of remaining beep tones is
decremented.

After that, the last LED that was on, is switched off. The LED
counter in incremented by one and is checked, if it is already
higher than 10. If yes, the two-second-counter is incremented
and checked, if this has reached 30. If yes, a minute is over and
the minute register is incremented. If that has exceeded 10, the
yellow LED is activated and a continous beep is initiated.

At the end, the next LED to be lit is calculated and, according to


the minute counter, is switched to red or green. For calculation of
the correct routine, the start address of a jump instruction table
(red or green) is written to the register pair ZH:ZL and the LED
number is added. By executing IJMP a jump to the correct
routine is performed. After switching the correct LED, the
routines all jump back to the sleep instruction of the main
program loop.

3.2 Variations

There is a broad palette of possible variations:


1. LED band speed:
❍ hectic mode: for people that need high speed, we increase the running speed of the LEDs to

the double, by reducing the value of 12500 down to 6250 and changing the 30 for the minute
recognition to 60.
❍ slow mode: for the one's that need more time to move their eyes, we change the 12500 to

25000 and change the 30 in the minute recognition to 15.


2. Incorrect LED order? No problem: exchange the lines
ldi ZH,HIGH(TabRot) ; try with red, and
ldi ZL,LOW(TabRot)
against the lines
ldi ZH,HIGH(TabGruen) ; no, it is green, and
ldi ZL,LOW(TabGruen)
and the line runs with opposite colors.
3. Higher tone? No problem, in the line
ldi rmp,63 ; CTC-value
just exchange 63 by a smaller value for timer 0.
4. Egg-timer for a musician? Possible. Just add a table with the CTC values of the gamut to the flash,
and, after each minute, change the CTC value with the next value in the table.
5. If your customer prefers hard-boiled eggs of the type "golfball": add four dual-LEDs to the four
available portpins and add them to the software.
6. ...

The number of possible variations makes it impossible to offer the software for all these variations. The
number of variations should be big enough to design an individual gift for each and everyone in your circle
of friends, so that no one gets a timer with exactly the same design. But: keep good records on all the
distributed variations. Otherwise you might run into new trouble.

And now: good luck with your handicrafts.

To the top of page

©2006 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/eggtimer/eggtimer.html1/20/2009 7:59:33 PM
http://www.avr-asm-tutorial.net/avr_en/source/eggtimer.asm

; **************************************************
; * ATtiny2313-Eggwatch, Version 1, 20.10.2006 *
; * (C)2006 by G.Schmidt info@avr-asm-tutorial.net *
; **************************************************
;
.NOLIST
.INCLUDE "tn2313def.inc"
.LIST
;
; ***************************************
; Fuses-setting in the ATtiny2313V
; ***************************************
;
; - Interal RC-Oscillator to 4 Mcs/s, CLKSEL3:0 = 0010, SUT1:0 = 10
; - Internal Clock prescaler to 8, CKDIV8 = Enabled
;
; ***************************************
; Hardware - scheme
; ***************************************
;
; __________
; / |_| |
; +3V O--|Res VCC|--O +3V
; | |
; L1K O--|PD0 PB7|--O L10A
; | |
;L1A/L2K O--|PD1 PB6|--O L9A/L10K
; | AT |
; O--|PA1 PB5|--O L8A/L9K
; | tiny |
; O--|PA0 PB4|--O L7A/L8K
; | 2313 |
;L2A/L3K O--|PD2 PB3|--O
; | V |
;L4K/L3A O--|PD3 PB2|--||--O Lsp
; | (OC0A)|
;L5K/L4A O--|PD4 PB1|--O
; | |
;L6K/L5A O--|PD5 PB0|--O L0K
; | |
; GND O--|GND PD6|--O L6A/L7K
; |___________|
;
;
; ***************************************
; Define Ports and Portbits
; ***************************************
;
.EQU pOcO = PORTB
.EQU dOcO = DDRB
.EQU bOcO = 2
;
.EQU pL0K = PORTB
.EQU dL0K = DDRB
.EQU bL0K = 0
;
.EQU pL1K = PORTD
.EQU dL1K = DDRD
.EQU bL1K = 0
;
.EQU pL1A = PORTD
.EQU dL1A = DDRD
.EQU bL1A = 1
;
.EQU pL2K = PORTD
.EQU dL2K = DDRD
.EQU bL2K = 1
;
.EQU pL2A = PORTD
.EQU dL2A = DDRD
.EQU bL2A = 2
;
.EQU pL3K = PORTD
.EQU dL3K = DDRD
.EQU bL3K = 2
;
.EQU pL3A = PORTD
.EQU dL3A = DDRD
.EQU bL3A = 3
;
.EQU pL4K = PORTD
.EQU dL4K = DDRD
.EQU bL4K = 3
;
.EQU pL4A = PORTD
.EQU dL4A = DDRD
.EQU bL4A = 4
;
.EQU pL5K = PORTD
.EQU dL5K = DDRD
.EQU bL5K = 4
;
.EQU pL5A = PORTD
.EQU dL5A = DDRD
.EQU bL5A = 5
;
.EQU pL6K = PORTD
.EQU dL6K = DDRD
.EQU bL6K = 5
;
.EQU pL6A = PORTD
.EQU dL6A = DDRD
.EQU bL6A = 6
;
.EQU pL7K = PORTD
.EQU dL7K = DDRD
.EQU bL7K = 6
;
.EQU pL7A = PORTB
.EQU dL7A = DDRB
.EQU bL7A = 4
;
.EQU pL8K = PORTB
.EQU dL8K = DDRB
.EQU bL8K = 4
;
.EQU pL8A = PORTB
.EQU dL8A = DDRB
.EQU bL8A = 5
;
.EQU pL9K = PORTB
.EQU dL9K = DDRB
.EQU bL9K = 5
;
.EQU pL9A = PORTB
.EQU dL9A = DDRB
.EQU bL9A = 6
;
.EQU pL10K = PORTB
.EQU dL10K = DDRB
.EQU bL10K = 6
;
.EQU pL10A = PORTB
.EQU dL10A = DDRB
.EQU bL10A = 7
;
; ***************************************
; Function of Timing
; ***************************************
;
; Timer1 = time measuring
; _______ ______ ______ ______ _____ ______
; |RC-Osc.| | CDiv |500|Presc.|62,5|TC1CNT|5cs| LED |0,5|MinCnt|
; | 4 Mcs |===>| / 8 |==>| / 8 |===>|/12500|==>|Count|==>| / 30 |==>1 Min.
; |_______| |______|kcs|______|kcs |______| |_____|cs |______|
; |
; Timer0= Audio-gener. |
; | ______ ______
; | |Presc.| |TC0CNT|992cs/s
; |=>| / 8 |==>| / 63 |===> OC0A = Beep-Loudspeaker
; |______| |______|
;
;
; ***************************************
; Register
; ***************************************
;
.DEF rmp = R16
.DEF rFlg = R17
.DEF rLed = R18
.DEF rSec = R19
.DEF rMin = R20
.DEF rNb = R21
;
; ***************************************
; Reset and Interrupt-Vectors
; ***************************************
;
.CSEG
.ORG $0000
rjmp Main ; Reset
reti ; INT0 Interrupt
reti ; INT1 Interrupt
reti ; TC1Capt Interrupt
rjmp TC1CmpA ; Timer 1 Compare A match
reti ; TC1 Overflow Int
reti ; TC0 Overflow Int
reti ; UART0 RX Int
reti ; UART0 TX Int
reti ; Ana Comp Int
reti ; PCINT
reti ; TC1 CompB Int
reti ; TC0 Compare Match A Int
reti ; TC0 Compare Match B Int
reti ; USISTART Int
reti ; USIOverflow Int
reti ; EERDY Int
reti ; WDT Overflow Int
;
; ***************************************
; TC1 Compare Match A Interrupt Routine
; ***************************************
;
TC1CmpA:
set
reti
;
; ***************************************
; Main program
; ***************************************
;
Main:
; Stack init
ldi rmp,LOW(RAMEND) ; Set Stack pointer
out SPL,rmp
; Init Register
ldi rFlg,0 ; Init Flag
ldi rLed,0 ; Init LEDs
ldi rSec,0 ; Init 0.5-Second counter
ldi rMin,1 ; Init Minute counter
ldi rNb,1 ; Init Beep-counter
; Init OCR0A-Output for Beep
sbi dOcO,bOcO
; Init Timer 1 for time measuring and LED control
ldi rmp,HIGH(12500) ; CTC-value
out OCR1AH,rmp
ldi rmp,LOW(12500)
out OCR1AL,rmp
clr rmp ; Controlword A
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS11) ; to CTC mode
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; Timer1-Interrupt
out TIMSK,rmp
; Init Timer 0 for Beep-Output
ldi rmp,(1<<COM0A0)|(1<<WGM01) ; CTC, Toggle Compare A
out TCCR0A,rmp
ldi rmp,1<<CS01 ; beep on
out TCCR0B,rmp
ldi rmp,63 ; CTC-value
out OCR0A,rmp
ldi rmp,1<<SE ; sleep idle
out MCUCR,rmp
sei ; Enable Ints
;
; ***************************************
; Main program - Loop
; ***************************************
;
; to sleep mode idle
An:
sleep ; Sleep on
nop ; wake up
brtc An ; T-Flag not activated by Timer
clt ; T-Flag reset
sbrc rLed,0 ; Bit 0 is Beep-control
rjmp BeepAus
tst rNb ; test beeps = 0
breq BeepAus ; switch Beeps off
ldi rmp,1<<CS01 ; beep on
out TCCR0B,rmp
dec rNb ; decrement Beeps
rjmp LedAus
BeepAus:
ldi rmp,0 ; Beep off, stop Timer
out TCCR0B,rmp
LedAus:
ldi ZH,HIGH(TabAus) ; jump table LED off
ldi ZL,LOW(TabAus)
add ZL,rLed ; add current LED
brcc MachAus
inc ZH
MachAus:
ijmp ; current LED deactivation
Aus: ; LED is off
inc rLed ; increase conter
cpi rLed,10 ; already at ten
brne Weiter ; no
clr rLed ; yes, start again
inc rSec ; inc 0.5-second counter
cpi rSec,30 ; reached 30?
brcs Weiter ; no, not yet
clr rSec ; yes, clear 0.5-second counter
mov rNb,rMin ; copy Minutes to Beep-counter
inc rMin ; inc Minute counter
cpi rMin,11 ; 10 Minutes over?
brcs Weiter ; no
clr rMin ; restart Minute counter
ldi rNb,255 ; Beep for a whole Minute
sbi dL0K,bL0K ; Output yellow LED on
cbi pL0K,bL0K ; yellow LED on
Weiter: ; current LED red or green?
ldi ZH,HIGH(TabRot) ; try with red
ldi ZL,LOW(TabRot)
cp rLed,rMin ; current LED smaller than Minute counter
brcs Weiter1 ; yes
ldi ZH,HIGH(TabGruen) ; no, it's green
ldi ZL,LOW(TabGruen)
Weiter1: ; switch LED on
add ZL,rLed ; add LED to base address
brcc MachAn
inc ZH
MachAn: ; switch LED on
ijmp
;
; ***************************************
; Jump tables
; ***************************************
;
; Jump table for LEDs red
TabRot:
rjmp L1R
rjmp L2R
rjmp L3R
rjmp L4R
rjmp L5R
rjmp L6R
rjmp L7R
rjmp L8R
rjmp L9R
rjmp L10R
; Jump table for LEDs green
TabGruen:
rjmp L1G
rjmp L2G
rjmp L3G
rjmp L4G
rjmp L5G
rjmp L6G
rjmp L7G
rjmp L8G
rjmp L9G
rjmp L10G
; Jump table for LEDs off
TabAus:
rjmp L1A
rjmp L2A
rjmp L3A
rjmp L4A
rjmp L5A
rjmp L6A
rjmp L7A
rjmp L8A
rjmp L9A
rjmp L10A
;
; ***************************************
; LED switching routines
; ***************************************
;
; LEDs off
L1A:
cbi pL1A,bL1A
cbi pL1K,bL1K
cbi dL1A,bL1A
cbi dL1K,bL1K
rjmp Aus
L2A:
cbi pL2A,bL2A
cbi pL2K,bL2K
cbi dL2A,bL2A
cbi dL2K,bL2K
rjmp Aus
L3A:
cbi pL3A,bL3A
cbi pL3K,bL3K
cbi dL3A,bL3A
cbi dL3K,bL3K
rjmp Aus
L4A:
cbi pL4A,bL4A
cbi pL4K,bL4K
cbi dL4A,bL4A
cbi dL4K,bL4K
rjmp Aus
L5A:
cbi pL5A,bL5A
cbi pL5K,bL5K
cbi dL5A,bL5A
cbi dL5K,bL5K
rjmp Aus
L6A:
cbi pL6A,bL6A
cbi pL6K,bL6K
cbi dL6A,bL6A
cbi dL6K,bL6K
rjmp Aus
L7A:
cbi pL7A,bL7A
cbi pL7K,bL7K
cbi dL7A,bL7A
cbi dL7K,bL7K
rjmp Aus
L8A:
cbi pL8A,bL8A
cbi pL8K,bL8K
cbi dL8A,bL8A
cbi dL8K,bL8K
rjmp Aus
L9A:
cbi pL9A,bL9A
cbi pL9K,bL9K
cbi dL9A,bL9A
cbi dL9K,bL9K
rjmp Aus
L10A:
cbi pL10A,bL10A
cbi pL10K,bL10K
cbi dL10A,bL10A
cbi dL10K,bL10K
rjmp Aus
; LEDs green
L1G:
sbi pL1A,bL1A
cbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2G:
sbi pL2A,bL2A
cbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3G:
sbi pL3A,bL3A
cbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4G:
sbi pL4A,bL4A
cbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5G:
sbi pL5A,bL5A
cbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6G:
sbi pL6A,bL6A
cbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7G:
sbi pL7A,bL7A
cbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8G:
sbi pL8A,bL8A
cbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9G:
sbi pL9A,bL9A
cbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10G:
sbi pL10A,bL10A
cbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
; LEDs red
L1R:
cbi pL1A,bL1A
sbi pL1K,bL1K
sbi dL1A,bL1A
sbi dL1K,bL1K
rjmp An
L2R:
cbi pL2A,bL2A
sbi pL2K,bL2K
sbi dL2A,bL2A
sbi dL2K,bL2K
rjmp An
L3R:
cbi pL3A,bL3A
sbi pL3K,bL3K
sbi dL3A,bL3A
sbi dL3K,bL3K
rjmp An
L4R:
cbi pL4A,bL4A
sbi pL4K,bL4K
sbi dL4A,bL4A
sbi dL4K,bL4K
rjmp An
L5R:
cbi pL5A,bL5A
sbi pL5K,bL5K
sbi dL5A,bL5A
sbi dL5K,bL5K
rjmp An
L6R:
cbi pL6A,bL6A
sbi pL6K,bL6K
sbi dL6A,bL6A
sbi dL6K,bL6K
rjmp An
L7R:
cbi pL7A,bL7A
sbi pL7K,bL7K
sbi dL7A,bL7A
sbi dL7K,bL7K
rjmp An
L8R:
cbi pL8A,bL8A
sbi pL8K,bL8K
sbi dL8A,bL8A
sbi dL8K,bL8K
rjmp An
L9R:
cbi pL9A,bL9A
sbi pL9K,bL9K
sbi dL9A,bL9A
sbi dL9K,bL9K
rjmp An
L10R:
cbi pL10A,bL10A
sbi pL10K,bL10K
sbi dL10A,bL10A
sbi dL10K,bL10K
rjmp An
;
; End of source code
;

http://www.avr-asm-tutorial.net/avr_en/source/eggtimer.asm1/20/2009 7:59:40 PM
Quellcode Schrittmotor-Steuerung mit ATtiny13

Pfad: Home => AVR overview => Applications => Steppermotor controller => Source code

Source code of
the Steppermotor
controller with an
ATtiny13

; ****************************************************
; * Steppermotor-Driver with an ATtiny13 - Version 1 *
; * (C)2007 by http://www.avr-asm-tutorial.net *
; ****************************************************
;
; Debugging switches
;
.equ debug_calc = 0
.equ debug_const = 0
.equ debug_out = 0
;
.nolist
.include "tn13def.inc"
.list ; ______
; / |
; Hardware: | |
; _______ . . +12V black
; ___ / | | | ___ |
; +5V-|___|--|RES VCC|--+5V B3-|I4 O4|-|___|-+Q4 red
; | | | | ___ |
; B3--|PB3 PB2|---------|I5 O5|-|___|-+Q2 brown
; | | | | ___ |
; Analog-In--|PB4 PB1|---------|I6 O6|-|___|-+Q3 green
; | | | | ___ |
; |--|GND PB0|---------|I7 O7|-|___|-+Q1 white
; |________| | | |
; ATtiny13 |-|GND CD|-------+
; |_______|
; ULN2003
;
; Funktioning:
; A stepper motor is controled by an analog input voltage
; on pin 3. The input voltage ranges from 0 Volt to
; the operating voltage of the processor. The number
; of steps of the motor over that input range are
; adjusted by the constant cSmSteps (1...65535 steps).
; Stepmotor drive sequence and encoding:
; Portbit PB0 PB2 PB1 PB3 | |
; Color wt bn gn rd | Portbit | Byte
; Step Q4 Q3 Q2 Q1 | 3 2 1 0 |
; ------------------------+---------+------
; 1 1 1 0 0 | 0 1 0 1 | 05
; 2 0 1 1 0 | 0 1 1 0 | 06
; 3 0 0 1 1 | 1 0 1 0 | 0A
; 4 1 0 0 1 | 1 0 0 1 | 09
; results in the word table: .dw 0x0605,0x090A
;
; Timer TC0:
; The timer runs with the processor clock of 1.2 Mcs/s
; with a prescaler value of 1024 in normal CTC mode,
; with the CompareA register as TOP value. Interrupt
; at CompareA match resp. at CTC reset.
; The interrupt service routine compares the actual
; value of motor steps with the target value. If the
; actual value is too low, the actual value is
; increased one step, if it is too high the actual
; step value is decreased. If actual and target value
; are equal, the coils of the motor are switched off
; after a certain pre-selectable delay.
; Timing: step frequency = 1.2 Mcs/s / 1024 / CompA,
; with CompA = 255: step frequency = 4.57 cs/s,
; with CompA = 8: step frequency = 146 cs/s
; ADC:
; Conversion of the analogue voltage on pin 3 / PB4 /ADC2,
; summing up 64 measuring results to average results,
; conversion to the target value for the stepper motor
; Timing: clock divider for conversion = 128,
; 1,2 Mcs/s / 128 = 9,375 kcs/s = 106,7 us clock rate,
; Conversion = 13 cycles = 1,387 ms per conversion
; = 721 conversions per second
; Averaging over 64 conversions = 88,75 ms = 11,3 results
; per second
;
; Constants
;
.equ cSmSteps = 1276 ; 2552/2, number of steps for full range
.equ cSmFreq = 145 ; frequency stepper motor
; Minimum: 5 cs/s, Maximum: 1171 cs/s
.equ cSmDelay = 390 ; number of cycles prior to switching off
;
; Derived constants
;
.equ clock = 1200000 ; clock frequency Tiny13 internal
.equ Tc0Ctc = 1024 ; prescaler value TC0
.equ cCmpA = clock / 1024 / cSmFreq ; CompareA value
;
; Checking the constants
;
.IF cCmpA > 255
.ERROR "Steppermotor frequency too low!"
.ENDIF
.IF cCmpA < 1
.ERROR "Steppermotor frequency too high!"
.ENDIF
;
; SRAM (not used, only for stack operation)
;
; Registers
;
; used: R0 for table reading
; used: R8:R1 for calculation of target value
; free: R10:R8
.def rAdcCL = R11 ; ADC calculation value LSB
.def rAdcCH = R12 ; dto., MSB
.def rAdcRL = R13 ; ADC transfer value LSB
.def rAdcRH = R14 ; dto., MSB
.def rSreg = R15 ; status save/restore register
.def rmp = R16 ; Multipurpose outside Int
.def rimp = R17 ; Multipurpose inside Int
.def rFlg = R18 ; Flags
.equ bAdc = 0 ; Adc conversion complete flag
.def rAdcC = R19 ; ADC counter (64 Adc conversions)
.def rAdcL = R20 ; ADC Adder register LSB
.def rAdcH = R21 ; dto., MSB
.def rSmSL = R22 ; Steppermotor target value LSB
.def rSmSH = R23 ; dto., MSB
.def rSmIL = R24 ; Steppermotor actual value LSB
.def rSmIH = R25 ; dto., MSB
; used: X for activation delay of the coils
; free: Y
; used: Z for table access
;
; **********************************
; Code Segment Start, Int - Vector
; **********************************
;
.cseg
.org $0000
;
rjmp Main ; Reset vector
reti ; INT0 vector
reti ; PCINT0 vector
reti ; TIM0_OVF vector
reti ; EE_RDY vector
reti ; ANA_COMP vector
rjmp Tc0IntCA ; TIM0_COMPA vector
reti ; TIM0_COMPB vector
reti ; WDT vector
rjmp AdcInt ; ADC vector
;
; **********************************
; Interrupt Service Routines
; **********************************
;
; Timer-Counter 0 Compare A Interrupt Service Routine
;
Tc0IntCA:
in rSreg,SREG ; save status
cp rSmIL,rSmSL ; compare actual with target value
cpc rSmIH,rSmSH
breq Tc0IntCA0 ; jump if equal
brcs Tc0IntCAF ; actual less than target value
sbiw rSmIL,1 ; actual greater than target, one step back
rjmp Tc0IntCAS
Tc0IntCAF:
adiw rSmIL,1 ; one step forward
Tc0IntCAS:
mov rimp,rSmIL ; copy actual value LSB
andi rimp,0x03 ; isolate lowest two bit
ldi ZH,HIGH(2*SmTab) ; point Z to table in flash memory
ldi ZL,LOW(2*SmTab)
add ZL,rimp ; add the two lowest bits
ldi rimp,0 ; update upper Byte
adc ZH,rimp
lpm ; read next value from table to R0
.IF debug_out == 0
out PORTB,R0 ; write value to port
.ENDIF
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
out SREG,rSreg ; restore status
reti
Tc0IntCA0:
sbiw XL,1 ; decrease delay counter
brne Tc0IntCAD ; not yet zero
ldi rimp,0 ; switch of current on coils
out PORTB,rimp ; to output driver
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
Tc0IntCAD:
out SREG,rSreg ; restore status
reti
;
SmTab:
.dw 0x0605,0x090A
;
; Adc Conversion Complete Interrupt Service Routine
;
AdcInt:
in rSreg,SREG ; save status
in rimp,ADCL ; read LSB of ADC result
add rAdcL,rimp ; add to the result register
in rimp,ADCH ; read MSB of ADC result
adc rAdcH,rimp ; add to the result register
dec rAdcC ; decrease counter
brne AdcInt1 ; if not zero, go on converting
mov rAdcRL,rAdcL ; 64 conversions, copy result
mov rAdcRH,rAdcH
clr rAdcH ; clear sum
clr rAdcL
ldi rAdcC,64 ; restart conversion counter
sbr rFlg,1<<bAdc ; set flag
AdcInt1:
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|
(1<<ADPS0)
out ADCSRA,rmp ; restart conversion
out SREG,rSreg ; restore status
reti
;
; **********************************
; Main program Init and Loop
; **********************************
;
Main:
; Stack init
ldi rmp, LOW(RAMEND)
out SPL,rmp
; Init register
clr rFlg ; clear flag register
clr rSmIL ; clear actual value
clr rSmIH
clr rSmSL ; clear target value
clr rSmSH
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
; Init output port
ldi rmp,0x0F ; output on portbits 0..3
out DDRB,rmp
ldi rmp,0x05 ; start motor at step 1
out PORTB,rmp
; Debugging session
.IF debug_calc
.equ adc_result = 128
ldi rmp,HIGH(adc_result)
mov rAdcRH,rmp
ldi rmp,LOW(adc_result)
mov rAdcRL,rmp
rjmp dcalc
.ENDIF
.IF debug_const
.equ const = cMSteps
ldi rmp,HIGH(const)
mov rSmSH,rmp
ldi rmp,LOW(const)
mov rSmSL,rmp
.ENDIF
; Init ADC
ldi rAdcC,64 ; restart ADC conversion counter
clr rAdcL ; clear ADC sum value
clr rAdcH
ldi rmp,1<<ADC2D ; Digital Input Disable on channel 2
out DIDR0,rmp
ldi rmp,1<<MUX1 ; ADC mux on channel 2
out ADMUX,rmp
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|
(1<<ADPS0)
out ADCSRA,rmp ; start conversion
; TC0 init
ldi rmp,cCmpA ; set CTC value
out OCR0A,rmp
ldi rmp,1<<WGM01 ; set CTC mode
out TCCR0A,rmp
ldi rmp,(1<<CS02)|(1<<CS00) ; prescaler = 1024
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Interrupt Compare Match A enable
out TIMSK0,rmp
; Sleep Mode and Int Enable
ldi rmp,1<<SE ; sleep enable
out MCUCR,rmp
sei ; Int enable
Loop:
sleep ; sleep
nop ; Dummy for wakeup
sbrc rFlg,bAdc ; ADC flag set?
rcall AdcRdy ; convert ADC result
rjmp Loop ; sleep again
;
; **********************************
; Calculation routine
; **********************************
;
; ADC conversion complete calculate target value
;
AdcRdy:
cbr rFlg,1<<bAdc ; clear ADC flag
.IF debug_const
ret
.ENDIF
dcalc:
mov rAdcCH,rAdcRH ; copy sum value
mov rAdcCL,rAdcRL
ldi rmp,LOW(cSmSteps) ; number of steps to R4:R3:R2:R1
mov R1,rmp
ldi rmp,HIGH(cSmSteps)
mov R2,rmp
clr R3
clr R4
clr R5 ; clear result in R8:R7:R6:R5
clr R6
clr R7
clr R8
AdcRdy1:
lsr rAdcCH ; shift lowest bit to carry flag
ror rAdcCL
brcc AdcRdy2 ; do not add
add R5,R1 ; add to result
adc R6,R2
adc R7,R3
adc R8,R4
AdcRdy2:
lsl R1 ; multiply multiplicator by two
rol R2
rol R3
rol R4
mov rmp,rAdcCL ; = zero?
or rmp,rAdcCH
brne AdcRdy1 ; go on multiplying
ldi rmp,0x80 ; round up
add R5,rmp
adc R6,rmp
ldi rmp,0
adc R7,rmp
adc R8,rmp
cli ; disable interrupts
mov rSmSL,R7 ; set target value LSB
mov rSmSH,R8 ; dto., set MSB
.IF debug_out
out PORTB,rSmSL
.ENDIF
sei ; enable interrupts again
ret
;
; End of Source Code
;

©2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/stepper/steppermotor_v1.html1/20/2009 7:59:45 PM
Steppermotor controller with ATtiny13

Pfad: Home => AVR overview => Applications => Steppermotor controller

Steppermotor controller with ATtiny13


This application of an AVR demonstrates controlling a steppermotor with an ATMEL ATtiny13,
with the following properties:

● Designed for cable drive remote steppermotors with a gear unit.


● An input voltage between 0..5 V with a resolution of 10 bits (1024 voltage steps, 4.88 mV per voltage step) controls the position of the steppermotor.
● Number of steps of the motor can be adjusted to up to 65,535 steps, so any gear unit and number of rotations of the motor can be selected by software.
● Simple driver for driving the motor.
● Very fast rotation of the motor can be achieved by optimizing the drive frequency.
● Reduction of current requirements by switching the coils of the motor off after a preselectable activation time following the last step.

0. Content
● 1. Hardware
❍ 1.1 Microcontroller

❍ 1.2 ISP-Interface

❍ 1.3 Coil current driver ULN2003A

❍ 1.4 Supply

● 2. Software
❍ 2.1 Functioning

❍ 2.2 Adjustments prior to assembling

❍ 2.3 Commented source code

1. Hardware
The hardware consists of the AVR processor ATtiny13, a six pin standard
programming connection for In-System-Programming (ISP), the 7-bit driver
ULN2003, the supply for the processor and the filtering of the analogue input
signal. The schematic diagram (click on it for a PDF page with higher
resolution):

1.1 Microcontroller

The processor ATtiny13 provides the following functions.


The operating voltage of 5 V is supplied to the pins 8 (+5 V) and 4 (0 V) and blocked with a ceramic capacitor of 100 nF.
Pin 1 (= RESET input) is tied with a resistor of 10 kOhm to the operating voltage.
Input PB4 (Pin 3) measures the analogue voltage, using the internal AD converter, by comparision with the operating voltage. From its conversion results,
software calculates the target value of the steppermotor's steps.
The output port pins PB0 to PB3 (pins 5, 6, 7 and 2) control the driver for the coils of the steppermotor.

1.2 ISP-Interface

The ISP interface serves as programming interface to program the AVR in the system. The pinout is ATMEL standard.
The ISP interface uses the port bits PB2 (SCK, Pin 7), PB1 (MISO, Pin 6), PB0 (MOSI, Pin 5) and the RESET at Pin 1. The operating voltage at VTG, if
connected, provides supply current to the programmer. Leave VTG open if the programmer provides its own supply. GND is reference for the negative
operating voltage.

1.3 Coil current driver ULN2003A

The drive current for the coils of the steppermotor is controlled by the driver IC ULN2003A. The outputs with open-collector-driver transistors allow for
voltages of up to 50 V and currents of up to 500 mA. They switch the different coils of the motor on aned off.
Induced inductive backdropping voltages, when coils are switched off, are shortcircuited by diodes, that are connected internally from each collector to the pin
CD. The motor used here is operated with a 12 V supply voltage and requires a current of approx. 150 mA per active coil (because there are alway two coils
active at a time, together 300 mA).
The input pins I7..I4 of the driver are controlled by the processor (active high, logic 1 switches coil on).

1.4 Supply

The supply voltages are filtered to avoid glitches by the switching coils. Supply of the coils is connected over a diode 1N4007 and smoothed by a capacitor of
100 µF.
The processor is supplied by a voltage stabilizer 78L05. Its input is connected to the 12 V supply over a diode 1N4007 and and capacitor of 100 µF. The
stabilizer is blocked with tantalum capacitors of 1 µF resp. 2,2 µF to avoid oscillations.
The supply and regulation of the controller/driver comes over a four-wire connection cable from a 12 V power supply (click on the picture to download a PDF
doc with higher resolution).

The 12 V supply is mounted on a small board.

2. Software
The software for the ATtiny13 is written in assembler, the source code is here for download.

2.1 Functioning

The software consists of the following basic elements:

● the Reset- and Interrupt vector table,


● the initialization of the starting values and the hardware components,
● the AD conversion of the input voltage,
● the calculation of the target value from the measured voltage,
● the step control and output to the steppermotor.

Reset- and interrupt vector table

The vector table redirects program execution to the main program, if a reset starts the processor. In case of an interrupt, the service routines for the timer/counter
and the AD converter are re-directing. Available vectors that are not used here are represented by RETI instructions.

Init of start values

Initiation of start values is coded starting with the label "Main:". Here

● the stack is initialized, because interrupts and subroutines are used,


● the flag register is cleared (see more about its function below),
● the registers holding the target and actual value of the steppermotor are cleared,
● the deactivation counter is set to its initial value.

Init of the hardware

Initing the hardware consists of:

● the direction of the four portbits PB0 to PB3 are set to be output and these bits are set to the first step of the motor,
● the AD conversion counter is set to 64, the sum value of the conversion result is cleared, the digital input driver if channel 2 at PB4 is switched off (the
PB4 pin is used exclusively for analog AD conversion), the AD mux is tied to channel ADC2, and the AD converter is inited with the following settings:
❍ reference voltage is the operating voltage of the ATtiny13,

❍ clock divider =128, at 1.2 Mcs/s internal clock and 13 clock cycles per conversion each conversion requires 1.387 ms, summing up of 64

conversion results yields a complete measuring cycle each 88.75 ms or 11.3 measuring cycles per second.
❍ Interrupt after each complete conversion,

❍ no automatic restart on conversion complete (restart is performed in the interrupt service routine).

● the timer/counter TC0 is set to normal CTC mode (clearing the counter when the compare value is reached), with the following settings:
❍ the duration of a CTC cycle is as long as the output signal for a single step ot the motor should last, this is controlled by the constant cCmpA, that

is written to the Compare register A of the counter,


❍ at the end of the CTC cycle an interrupt is triggered, the Compare-Match-Interrupt A is enabled,

❍ the clock prescaler is set to 1024 and the timer is started, the counter clock is therefore 1.2 Mcs/s / 1024 = 1.172 kcs/s, with CTC values between

1 and 255 yield frequencies between 1172 and 4.6 cs/s for the steps of the motor.
● the processor is set to sleep mode idle, that means: between the interrupts of the counter and the AD converter program execution is stopped.

AD converter measurements of the input voltage

The AD converter converts the input voltage on pin 3 (PB4, ADC2) to a value between 0..1023 and triggers a Conversion Complete Interrupt. The Interrupt
Service Routine, starting at the label "AdcInt:" reads the result from the ports ADCL und ADCH and sums it to the register pair rAdcH:rAdcL. The counter
rAdc is decreased by one. If rAdc reaches zero, the sum value is copied to the register pair rAdcRH:rAdcRL, the sum is cleareed, the counter is again set its
initial value 64 and the flag bAdc in the flag register is set to one. Finally, the next conversion is started.
Summing up 64 conversion results results in an averaging over these values, removing random results and fluctuations in the input signal, and slows down the
measuring process to a convenient cycle duration. The resulting sum value is between zero and 65,535 (0x0000..0xFFFF), an excellent basis for the following
calculation of the target value.

Conversion of the measuring result to the target value

If after waking up the processor and exection of the interrupt service routine the flag rAdc in the flag register is set, the conversion routine starting with the label
"AdcRdy:" is called. This routine

● clears the flag bit again,


● copies the sum value to the register pair rAdcCH:rAdcL,
● multiplies the sum value with the constant cSmSteps (the number of forward steps for the fullscale operation of the motor) to yield a 32-bit result,
● rounds the lower 16 bits of this number,
● divides the 32-bit result by 65,536 (by ignoring the lower 16 bits), resulting in the target value as 16 bit number, and
● writes this result to the target value register pair rSmSH:rSmSL (during which interrupts are disabled to avoid errors in the motor adjustment, should
there be a timer interrupt between copying LSB and MSB).

Step control and output to the motor

The step control and output to the steppermotor is done in the interrupt service routine of the counter, starting with the label "Tc0IntCA:".
First, the actual and the target value registers are compared. If they are equal, a jump to the label "Tc0IntCA0:" is executed. There, the delay counter in the
register pair X is decreased by one. If the delay counter reaches zero, the coils are de-energized by writing zeroes to the driving port bits, the delay counter is
restarted and the service routine is left.
If the actual and the target value are not equal, the actual value is incresed or decreased. This new value is translated like follows to a new value for the stepper
driver:

● the two lowest bits of the (new) actual value are isolated, and
● are added to the start address of the table "SmTab:" in Z, that points to the respective table in the flash memory,
● with the instruction LPM, the byte at that address is read to R0, and
● this is written to the output port, which switches the correct coils of the motor on/off.

The table "SmTab:" with the two words 0x0605 and 0x090A determines the step sequence of the steppermotor as follows:

● Step 1: 0x05, binary 0 1 0 1,


● Step 2: 0x06, binary 0 1 1 0,
● Step 3: 0x0A, binary 1 0 1 0,
● Step 4: 0x09, binary 1 0 0 1.

Note: If the coils Q1..Q4 of the stepper are connected in a different manner to the driver outputs, it is necessary and sufficient to change these two words (see
below).
In the service routine finally the delay counter is restarted, to keep the coils activated for the appropriate preselected time, after changing the output pattern.

2.2 Adjustments prior to assembling

In the assembler source code, the following adjustments must/can be made prior to assembling the code:

● The three debug switches debug_calc, debug_const and debug_out must be set to zero!
● The constant cSmSteps should be adjusted to the number of steps that the motor should perform over the whole range (maximum: 65,535).
● The constant cSmFreq must be adjusted to the frequency that the motor is reliably moving (minimum 5 cs/s - for extremely large motors, maximum
1171 cs/s - far too fast for most types of motors).
● the constant cSmDelay sets the number of cycles, for which the coils stay activated, after having changed the drive pattern of the motor. If cSmDelay is
equal to cSmFreq, the delay is exactly one second.

The order of the four coils on connector J2 might be different with different types of motors. If a different order is to be adapted, it is sufficient to change the
table SmTab:.
The current table is made for a KP4M4-001 type and is generated as follows:

Coil color Portbit Step 1 Step 2 Step3 Step 4


Q1 red PB3 0 0 1 1
Q2 green PB1 0 1 1 0
Q3 brown PB2 1 1 0 0
Q4 white PB0 1 0 0 1

The resulting table code is as follows:

Coil Portbit
Step Byte Word
Q4 Q3 Q2 Q1 PB3 PB2 PB1 PB0
1 1 1 0 0 0 1 0 1 0x05
0x0605
2 0 1 1 0 0 1 1 0 0x06
3 0 0 1 1 1 0 1 0 0x0A
0x090A
4 1 0 0 1 1 0 0 1 0x09

2.3 Commented source code

The source code is available in .asm text format here, in .html format here.

©2007 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/stepper/stepper.html1/20/2009 8:00:00 PM
http://www.avr-asm-tutorial.net/avr_en/source/steppermotor_v1.asm

; ****************************************************
; * Steppermotor-Driver with an ATtiny13 - Version 1 *
; * (C)2007 by http://www.avr-asm-tutorial.net *
; ****************************************************
;
; Debugging switches
;
.equ debug_calc = 0
.equ debug_const = 0
.equ debug_out = 0
;
.nolist
.include "tn13def.inc"
.list ; ______
; / |
; Hardware: | |
; _______ . . +12V black
; ___ / | | | ___ |
; +5V-|___|--|RES VCC|--+5V B3-|I4 O4|-|___|-+Q4 red
; | | | | ___ |
; B3--|PB3 PB2|---------|I5 O5|-|___|-+Q2 brown
; | | | | ___ |
; Analog-In--|PB4 PB1|---------|I6 O6|-|___|-+Q3 green
; | | | | ___ |
; |--|GND PB0|---------|I7 O7|-|___|-+Q1 white
; |________| | | |
; ATtiny13 |-|GND CD|-------+
; |_______|
; ULN2003
;
; Funktioning:
; A stepper motor is controled by an analog input voltage
; on pin 3. The input voltage ranges from 0 Volt to
; the operating voltage of the processor. The number
; of steps of the motor over that input range are
; adjusted by the constant cSmSteps (1...65535 steps).
; Stepmotor drive sequence and encoding:
; Portbit PB0 PB2 PB1 PB3 | |
; Color wt bn gn rd | Portbit | Byte
; Step Q4 Q3 Q2 Q1 | 3 2 1 0 |
; ------------------------+---------+------
; 1 1 1 0 0 | 0 1 0 1 | 05
; 2 0 1 1 0 | 0 1 1 0 | 06
; 3 0 0 1 1 | 1 0 1 0 | 0A
; 4 1 0 0 1 | 1 0 0 1 | 09
; results in the word table: .dw 0x0605,0x090A
;
; Timer TC0:
; The timer runs with the processor clock of 1.2 Mcs/s
; with a prescaler value of 1024 in normal CTC mode,
; with the CompareA register as TOP value. Interrupt
; at CompareA match resp. at CTC reset.
; The interrupt service routine compares the actual
; value of motor steps with the target value. If the
; actual value is too low, the actual value is
; increased one step, if it is too high the actual
; step value is decreased. If actual and target value
; are equal, the coils of the motor are switched off
; after a certain pre-selectable delay.
; Timing: step frequency = 1.2 Mcs/s / 1024 / CompA,
; with CompA = 255: step frequency = 4.57 cs/s,
; with CompA = 8: step frequency = 146 cs/s
; ADC:
; Conversion of the analogue voltage on pin 3 / PB4 /ADC2,
; summing up 64 measuring results to average results,
; conversion to the target value for the stepper motor
; Timing: clock divider for conversion = 128,
; 1,2 Mcs/s / 128 = 9,375 kcs/s = 106,7 us clock rate,
; Conversion = 13 cycles = 1,387 ms per conversion
; = 721 conversions per second
; Averaging over 64 conversions = 88,75 ms = 11,3 results
; per second
;
; Constants
;
.equ cSmSteps = 1276 ; 2552/2, number of steps for full range
.equ cSmFreq = 145 ; frequency stepper motor
; Minimum: 5 cs/s, Maximum: 1171 cs/s
.equ cSmDelay = 390 ; number of cycles prior to switching off
;
; Derived constants
;
.equ clock = 1200000 ; clock frequency Tiny13 internal
.equ Tc0Ctc = 1024 ; prescaler value TC0
.equ cCmpA = clock / 1024 / cSmFreq ; CompareA value
;
; Checking the constants
;
.IF cCmpA > 255
.ERROR "Steppermotor frequency too low!"
.ENDIF
.IF cCmpA < 1
.ERROR "Steppermotor frequency too high!"
.ENDIF
;
; SRAM (not used, only for stack operation)
;
; Registers
;
; used: R0 for table reading
; used: R8:R1 for calculation of target value
; free: R10:R8
.def rAdcCL = R11 ; ADC calculation value LSB
.def rAdcCH = R12 ; dto., MSB
.def rAdcRL = R13 ; ADC transfer value LSB
.def rAdcRH = R14 ; dto., MSB
.def rSreg = R15 ; status save/restore register
.def rmp = R16 ; Multipurpose outside Int
.def rimp = R17 ; Multipurpose inside Int
.def rFlg = R18 ; Flags
.equ bAdc = 0 ; Adc conversion complete flag
.def rAdcC = R19 ; ADC counter (64 Adc conversions)
.def rAdcL = R20 ; ADC Adder register LSB
.def rAdcH = R21 ; dto., MSB
.def rSmSL = R22 ; Steppermotor target value LSB
.def rSmSH = R23 ; dto., MSB
.def rSmIL = R24 ; Steppermotor actual value LSB
.def rSmIH = R25 ; dto., MSB
; used: X for activation delay of the coils
; free: Y
; used: Z for table access
;
; **********************************
; Code Segment Start, Int - Vector
; **********************************
;
.cseg
.org $0000
;
rjmp Main ; Reset vector
reti ; INT0 vector
reti ; PCINT0 vector
reti ; TIM0_OVF vector
reti ; EE_RDY vector
reti ; ANA_COMP vector
rjmp Tc0IntCA ; TIM0_COMPA vector
reti ; TIM0_COMPB vector
reti ; WDT vector
rjmp AdcInt ; ADC vector
;
; **********************************
; Interrupt Service Routines
; **********************************
;
; Timer-Counter 0 Compare A Interrupt Service Routine
;
Tc0IntCA:
in rSreg,SREG ; save status
cp rSmIL,rSmSL ; compare actual with target value
cpc rSmIH,rSmSH
breq Tc0IntCA0 ; jump if equal
brcs Tc0IntCAF ; actual less than target value
sbiw rSmIL,1 ; actual greater than target, one step back
rjmp Tc0IntCAS
Tc0IntCAF:
adiw rSmIL,1 ; one step forward
Tc0IntCAS:
mov rimp,rSmIL ; copy actual value LSB
andi rimp,0x03 ; isolate lowest two bit
ldi ZH,HIGH(2*SmTab) ; point Z to table in flash memory
ldi ZL,LOW(2*SmTab)
add ZL,rimp ; add the two lowest bits
ldi rimp,0 ; update upper Byte
adc ZH,rimp
lpm ; read next value from table to R0
.IF debug_out == 0
out PORTB,R0 ; write value to port
.ENDIF
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
out SREG,rSreg ; restore status
reti
Tc0IntCA0:
sbiw XL,1 ; decrease delay counter
brne Tc0IntCAD ; not yet zero
ldi rimp,0 ; switch of current on coils
out PORTB,rimp ; to output driver
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
Tc0IntCAD:
out SREG,rSreg ; restore status
reti
;
SmTab:
.dw 0x0605,0x090A
;
; Adc Conversion Complete Interrupt Service Routine
;
AdcInt:
in rSreg,SREG ; save status
in rimp,ADCL ; read LSB of ADC result
add rAdcL,rimp ; add to the result register
in rimp,ADCH ; read MSB of ADC result
adc rAdcH,rimp ; add to the result register
dec rAdcC ; decrease counter
brne AdcInt1 ; if not zero, go on converting
mov rAdcRL,rAdcL ; 64 conversions, copy result
mov rAdcRH,rAdcH
clr rAdcH ; clear sum
clr rAdcL
ldi rAdcC,64 ; restart conversion counter
sbr rFlg,1<<bAdc ; set flag
AdcInt1:
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; restart conversion
out SREG,rSreg ; restore status
reti
;
; **********************************
; Main program Init and Loop
; **********************************
;
Main:
; Stack init
ldi rmp, LOW(RAMEND)
out SPL,rmp
; Init register
clr rFlg ; clear flag register
clr rSmIL ; clear actual value
clr rSmIH
clr rSmSL ; clear target value
clr rSmSH
ldi XH,HIGH(cSmDelay) ; restart delay counter
ldi XL,LOW(cSmDelay)
; Init output port
ldi rmp,0x0F ; output on portbits 0..3
out DDRB,rmp
ldi rmp,0x05 ; start motor at step 1
out PORTB,rmp
; Debugging session
.IF debug_calc
.equ adc_result = 128
ldi rmp,HIGH(adc_result)
mov rAdcRH,rmp
ldi rmp,LOW(adc_result)
mov rAdcRL,rmp
rjmp dcalc
.ENDIF
.IF debug_const
.equ const = cMSteps
ldi rmp,HIGH(const)
mov rSmSH,rmp
ldi rmp,LOW(const)
mov rSmSL,rmp
.ENDIF
; Init ADC
ldi rAdcC,64 ; restart ADC conversion counter
clr rAdcL ; clear ADC sum value
clr rAdcH
ldi rmp,1<<ADC2D ; Digital Input Disable on channel 2
out DIDR0,rmp
ldi rmp,1<<MUX1 ; ADC mux on channel 2
out ADMUX,rmp
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; start conversion
; TC0 init
ldi rmp,cCmpA ; set CTC value
out OCR0A,rmp
ldi rmp,1<<WGM01 ; set CTC mode
out TCCR0A,rmp
ldi rmp,(1<<CS02)|(1<<CS00) ; prescaler = 1024
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Interrupt Compare Match A enable
out TIMSK0,rmp
; Sleep Mode and Int Enable
ldi rmp,1<<SE ; sleep enable
out MCUCR,rmp
sei ; Int enable
Loop:
sleep ; sleep
nop ; Dummy for wakeup
sbrc rFlg,bAdc ; ADC flag set?
rcall AdcRdy ; convert ADC result
rjmp Loop ; sleep again
;
; **********************************
; Calculation routine
; **********************************
;
; ADC conversion complete calculate target value
;
AdcRdy:
cbr rFlg,1<<bAdc ; clear ADC flag
.IF debug_const
ret
.ENDIF
dcalc:
mov rAdcCH,rAdcRH ; copy sum value
mov rAdcCL,rAdcRL
ldi rmp,LOW(cSmSteps) ; number of steps to R4:R3:R2:R1
mov R1,rmp
ldi rmp,HIGH(cSmSteps)
mov R2,rmp
clr R3
clr R4
clr R5 ; clear result in R8:R7:R6:R5
clr R6
clr R7
clr R8
AdcRdy1:
lsr rAdcCH ; shift lowest bit to carry flag
ror rAdcCL
brcc AdcRdy2 ; do not add
add R5,R1 ; add to result
adc R6,R2
adc R7,R3
adc R8,R4
AdcRdy2:
lsl R1 ; multiply multiplicator by two
rol R2
rol R3
rol R4
mov rmp,rAdcCL ; = zero?
or rmp,rAdcCH
brne AdcRdy1 ; go on multiplying
ldi rmp,0x80 ; round up
add R5,rmp
adc R6,rmp
ldi rmp,0
adc R7,rmp
adc R8,rmp
cli ; disable interrupts
mov rSmSL,R7 ; set target value LSB
mov rSmSH,R8 ; dto., set MSB
.IF debug_out
out PORTB,rSmSL
.ENDIF
sei ; enable interrupts again
ret
;
; End of Source Code
;

http://www.avr-asm-tutorial.net/avr_en/source/steppermotor_v1.asm1/20/2009 8:00:07 PM
Connecting a LCD display to a STK500 port

Pfad: Home => AVR-Overview => 2-Line-LCD on STK500

Connecting a 2-line-LCD to a STK500 port


The develloper board STK500 doesn't come with a LCD interface for connecting a cheap display,
like STK200 does. But even the STK200-LCD-port has some disadvantages: It requires talking to the
LCD in memory mapped mode, which means, that the LCD interface blocks external SRAM space
and requires slowing down the CPU with extra wait states. But it is easy to connect such a display to
a port of the processor directly, without using memory mapping. It requires only 6 port bits, and the
software is very easy, if you skip reading the display memory. The data sent to the LCD is divided in
packages to 4 bits each. Hardware is rather easy, too. One disadvantage is that you have to do the
timing without reading the display's enable bit, requiring some adjusted delay loops. But that is not
too bad.

Hardware
The hardware is shown in the following scheme:

So its only connecting the


correct

● Port-Bit to the appropriate


LCD-Pin,
● voltage source pins to the

ones on the LCD display, and


the correct
● pot pins to the contrast

adjustment pins of the LCD.

That's all for the hardware.

Software
The software for talking to the
LCD is completely separated in
the file LCD4INCE.html in
HTML-format and in the file
Lcd4IncE.asm in source file
format. The following routines
are provided:

1. Lcd4Init: This routine resets the LCD,


2. Lcd4Chr: This displays the char in rmp on the LCD,
3. Lcd4PBcd: This displays the packed BCD in rmp on the LCD,
4. Lcd4ZTxt: This displays the null-terminated text in the flash memory on the LCD, using the Z
pointer,
5. Lcd4RTxt: This displays rmp chars in SRAM where Z points to.

The software can be included in an existing program. The header in the file lists the requirements,
that the source file must fulfil to work correctly with the LCD rountines.

Test program
As a demonstration and test program a software clock has been programmed. This program displays
date and time of a software clock on the LCD. The program is listed in the file LCDINCCE.html in
HTML-format and in the file Lcd4IncCE.asm in source format. Sorry that you currently can not
adjust the clock. If you like, you can add some lines of code to use the switches or the UART via the
PC to adjust the software clock.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/LCD4_500.html1/20/2009 8:00:29 PM
Connecting a LCD display to a STK500 <A HREF="beginner/COMMANDS.html#Ports">port</A>

Pfad: Home => AVR-Overview => 2-Line-LCD on STK500 => LCD base routines

; ********************************************
; * LCD-base routines for 4-Bit-interface *
; * of a 2-line LCD display to an ATMEL- *
; * Port, Bits 4..7=Data, Bit 1=RS, Bit0=E *
; * Version 1, February 2002, (C) 2002 by *
; * Gerhard Schmidt, bug reports and sug- *
; * gestions to info!at!avr-asm-tutorial.net *
; ********************************************
;
; Hardware: LCD-Display on the active port
;
; Definitions, that must be dfeined in the calling
; program:
; - Stack operations must be initialised
; - Register rmp (R16..R31)
; - Clock frequency ftakt
; - pLcdPort Active LCD-Port
; - pLcdDdr Data direction registerof the active port
; Subroutines:
; - Lcd4Init: Initialise the LCD
; - Lcd4Chr: Display the character in rmp on the LCD
; - Lcd4PBcd: Display the packed BCD in rmp on the LCD
; - Lcd4ZTxt: Display the null-terminated string on the LCD
; - Lcd4RTxt: Display rmp chars from SRAM, starting at Z
;
; Definition for the LCD-port
.EQU cLcdWrite=0b11111111 ; Data direction write the LCD
.EQU cLcdDummy=0b00111000 ; Dummy-Function-Word
.EQU mLcdRs=0b00000010 ; RS-Bit Mask
.EQU bLcdEn=0 ; Enable Bit
.EQU c1s=200 ; Wait at start-up time (200 * 5 ms)
.EQU c5ms=ftakt/800 ; 5 ms Wait after each control word
.EQU c50us=ftakt/80000 ; 50 us Wait after each char
;
; Macro for Enable active time
;
; Version for 10 Mcs clock
;.MACRO enactive
; nop
; nop
; nop
; nop
; nop
;.ENDMACRO
;
; Version für 4 Mcs clock
;
.MACRO enactive
nop
nop
.ENDMACRO
;
Lcd4Init:
rcall LcdDelay1s ; Wait a second for the LCD
ldi rmp,cLcdWrite ; Data direction to output
out pLcdDdr,rmp
ldi rmp,cLcdDummy ; Dummy to catch LCD
rcall Lcd4Set ; send three times with 5 ms delay
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,0b00101000 ; Function Set to 4 Bit
rcall Lcd4Ctrl ; output on the Control Port LCD
ldi rmp,0b00010100 ; Cursor display shift
rcall Lcd4Ctrl
ldi rmp,0b00001100 ; LCD on
rcall Lcd4Ctrl
ldi rmp,0b00000110 ; Entry mode
rcall Lcd4Ctrl
Lcd4Clear:
ldi rmp,0b00000001 ; Set Lcd Clear
rcall Lcd4Ctrl
Lcd4Home:
ldi rmp,0b00000010 ; Set LCD Home Position
;
; Output of rmp on the Control-Port of the LCD
;
Lcd4Ctrl:
push rmp ; save byte
andi rmp,0xF0 ; clear lower nibble
rcall Lcd4Set ; output upper nibble
pop rmp ; restore byte
swap rmp ; swap lower and upper nibble
andi rmp,0xF0 ; clear lower nibble
rcall Lcd4Set ; output lower nibble
rjmp LcdDelay5ms ; done.
;
; Display the packed BCD in rmp on the LCD
;
Lcd4PBcd:
push rmp ; Save on stack
swap rmp ; Higher to lower nibble
rcall Lcd4PBcd1 ; Output nibble
pop rmp ; Restore from stack
Lcd4PBcd1:
andi rmp,0x0F ; Mask upper nibble
ori rmp,0x30 ; Nibble to ASCII
;
; Display char in rmp on the LCD
;
Lcd4Chr:
push rmp ; save char on stack
andi rmp,0xF0 ; clear lower nibble
sbr rmp,mLcdRs ; Set RS-Bit
rcall Lcd4Set ; output nibble
pop rmp ; get char from stack
swap rmp ; swap nibbles
andi rmp,0xF0 ; clear lower nibble
sbr rmp,mLcdRs ; Set RS-Bit
rcall Lcd4Set ; output nibble
rjmp LcdDelay50us ; ready
;
; Send nibble in rmp to LCD
;
Lcd4Set:
out pLcdPort,rmp ; Byte to output port
nop
sbi pLcdPort,bLcdEn ; Set Enable-Bit
enactive ; Delay macro
cbi pLcdPort,bLcdEn ; Clear Enable Bit
nop
ret
;
; Delay by 1 second on start-up
;
LcdDelay1s:
ldi rmp,c1s ; 200 * 5 ms wait
LcdDelay1s1:
rcall LcdDelay5ms
dec rmp
brne LcdDelay1s1
ret
;
; Delay by 5 ms following each Control Word
;
LcdDelay5ms:
push ZH
push ZL
ldi ZH,HIGH(c5ms)
ldi ZL,LOW(c5ms)
LcdDelay5ms1:
sbiw ZL,1
brne LcdDelay5ms1
pop ZL
pop ZH
ret
;
; Delay by 50 Microseconds after each Char
;
LcdDelay50us:
ldi rmp,c50us
LcdDelay50us1:
nop
dec rmp
brne LcdDelay50us1
ret
;
; Display at the position in rmp the string starting at Z (null-
term.)
;
Lcd4ZTxt:
sbr rmp,0b10000000 ; Set DD-RAM-Adress
rcall Lcd4Ctrl
Lcd4ZTxt1:
lpm ; Get a char
tst R0 ; Null-Char?
breq Lcd4ZTxtR
mov rmp,R0
rcall Lcd4Chr ; display the cahr in rmp
adiw ZL,1 ; next char
rjmp Lcd4ZTxt1 ; do it again
Lcd4ZTxtR:
ret
;
; Display rmp chars from SRAM starting at Z on the LCD
;
Lcd4RTxt:
mov R0,rmp ; R0 is counter
Lcd4RTxt1:
ld rmp,Z+ ; read char
rcall Lcd4Chr
dec R0
brne Lcd4RTxt1
ret

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/LCD4INCE.html1/20/2009 8:00:32 PM
http://www.avr-asm-tutorial.net/avr_en/source/Lcd4IncE.asm

; *****************************************
; * LCD-base routines for 4-Bit-interface *
; * of a 2-line LCD display to an ATMEL- *
; * Port, Bits 4..7=Data, Bit 1=RS, Bit0=E*
; * Version 1, February 2002, (C) 2002 by *
; * Gerhard Schmidt, bug reports and sug- *
; * gestions to info@avr-asm-tutorial.net *
; *****************************************
;
; Hardware: LCD-Display on the active port
;
; Definitions, that must be defined in the calling
; program:
; - Stack operations must be initialised
; - Register rmp (R16..R31)
; - Clock frequency ftakt
; - pLcdPort Active LCD-Port
; - pLcdDdr Data direction registerof the active port
; Subroutines:
; - Lcd4Init: Initialise the LCD
; - Lcd4Chr: Display the character in rmp on the LCD
; - Lcd4PBcd: Display the packed BCD in rmp on the LCD
; - Lcd4ZTxt: Display the null-terminated string on the LCD
; - Lcd4RTxt: Display rmp chars from SRAM, starting at Z
;
; Definition for the LCD-port
.EQU cLcdWrite=0b11111111 ; Data direction write the LCD
.EQU cLcdDummy=0b00111000 ; Dummy-Function-Word
.EQU mLcdRs=0b00000010 ; RS-Bit Mask
.EQU bLcdEn=0 ; Enable Bit
.EQU c1s=200 ; Wait at start-up time (200 * 5 ms)
.EQU c5ms=ftakt/800 ; 5 ms Wait after each control word
.EQU c50us=ftakt/80000 ; 50 us Wait after each char
;
; Macro for Enable active time
;
; Version for 10 Mcs clock
;.MACRO enactive
; nop
; nop
; nop
; nop
; nop
;.ENDMACRO
;
; Version für 4 Mcs clock
;
.MACRO enactive
nop
nop
.ENDMACRO
;
Lcd4Init:
rcall LcdDelay1s ; Wait a second for the LCD
ldi rmp,cLcdWrite ; Data direction to output
out pLcdDdr,rmp
ldi rmp,cLcdDummy ; Dummy to catch LCD
rcall Lcd4Set ; send three times with 5 ms delay
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,cLcdDummy
rcall Lcd4Set
rcall LcdDelay5ms
ldi rmp,0b00101000 ; Function Set to 4 Bit
rcall Lcd4Ctrl ; output on the Control Port LCD
ldi rmp,0b00010100 ; Cursor display shift
rcall Lcd4Ctrl
ldi rmp,0b00001100 ; LCD on
rcall Lcd4Ctrl
ldi rmp,0b00000110 ; Entry mode
rcall Lcd4Ctrl
Lcd4Clear:
ldi rmp,0b00000001 ; Set Lcd Clear
rcall Lcd4Ctrl
Lcd4Home:
ldi rmp,0b00000010 ; Set LCD Home Position
;
; Output of rmp on the Control-Port of the LCD
;
Lcd4Ctrl:
push rmp ; save byte
andi rmp,0xF0 ; clear lower nibble
rcall Lcd4Set ; output upper nibble
pop rmp ; restore byte
swap rmp ; swap lower and upper nibble
andi rmp,0xF0 ; clear lower nibble
rcall Lcd4Set ; output lower nibble
rjmp LcdDelay5ms ; done.
;
; Display the packed BCD in rmp on the LCD
;
Lcd4PBcd:
push rmp ; Save on stack
swap rmp ; Higher to lower nibble
rcall Lcd4PBcd1 ; Output nibble
pop rmp ; Restore from stack
Lcd4PBcd1:
andi rmp,0x0F ; Mask upper nibble
ori rmp,0x30 ; Nibble to ASCII
;
; Display char in rmp on the LCD
;
Lcd4Chr:
push rmp ; save char on stack
andi rmp,0xF0 ; clear lower nibble
sbr rmp,mLcdRs ; Set RS-Bit
rcall Lcd4Set ; output nibble
pop rmp ; get char from stack
swap rmp ; swap nibbles
andi rmp,0xF0 ; clear lower nibble
sbr rmp,mLcdRs ; Set RS-Bit
rcall Lcd4Set ; output nibble
rjmp LcdDelay50us ; ready
;
; Send nibble in rmp to LCD
;
Lcd4Set:
out pLcdPort,rmp ; Byte to output port
nop
sbi pLcdPort,bLcdEn ; Set Enable-Bit
enactive ; Delay macro
cbi pLcdPort,bLcdEn ; Clear Enable Bit
nop
ret
;
; Delay by 1 second on start-up
;
LcdDelay1s:
ldi rmp,c1s ; 200 * 5 ms wait
LcdDelay1s1:
rcall LcdDelay5ms
dec rmp
brne LcdDelay1s1
ret
;
; Delay by 5 ms following each Control Word
;
LcdDelay5ms:
push ZH
push ZL
ldi ZH,HIGH(c5ms)
ldi ZL,LOW(c5ms)
LcdDelay5ms1:
sbiw ZL,1
brne LcdDelay5ms1
pop ZL
pop ZH
ret
;
; Delay by 50 Microseconds after each Char
;
LcdDelay50us:
ldi rmp,c50us
LcdDelay50us1:
nop
dec rmp
brne LcdDelay50us1
ret
;
; Display at the position in rmp the string starting at Z (null-term.)
;
Lcd4ZTxt:
sbr rmp,0b10000000 ; Set DD-RAM-Adress
rcall Lcd4Ctrl
Lcd4ZTxt1:
lpm ; Get a char
tst R0 ; Null-Char?
breq Lcd4ZTxtR
mov rmp,R0
rcall Lcd4Chr ; display the cahr in rmp
adiw ZL,1 ; next char
rjmp Lcd4ZTxt1 ; do it again
Lcd4ZTxtR:
ret
;
; Display rmp chars from SRAM starting at Z on the LCD
;
Lcd4RTxt:
mov R0,rmp ; R0 is counter
Lcd4RTxt1:
ld rmp,Z+ ; read char
rcall Lcd4Chr
dec R0
brne Lcd4RTxt1
ret

http://www.avr-asm-tutorial.net/avr_en/source/Lcd4IncE.asm1/20/2009 8:00:33 PM
Connecting a LCD display to a STK500 <A HREF="beginner/COMMANDS.html#Ports">port</A>

Pfad: Home => AVR-Overview => 2-Line-LCD on STK500 => demo clock

; ***************************************************************
; * Clock with a 2-line-LCD for STK500 using Timer/Counter1 *
; * Connect the LCD over a 4-bit-data cable to the Port A *
; * Bit0=E, Bit1=RS, Bit4..7:D4..D7 *
; * Includes the LCD basic routines in Lcd4IncE.asm *
; * Adjusted to the board's clock of 3.685 MHz (STK500) *
; * (C)2002 by info!at!avr-asm-tutorial.net *
; * Created: 16.2.2002, Last change: 28.02.2002 *
; ***************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Timing-Scheme to create the 1-second-clock
;
;3.685.000Hz--> 460.625Hz --> 67 Hz --> 1 Hz
;
;+---------+ +----------+ +----------+ +--------+
;|CPU-Clock| |TC1-Divid.| |TC1-Compa-| |Register|
;|3,685 Mcs|-->|Prescaler |-->|re Match A|-->| rdiv1s |--> 1 s
;|7,37Mcs/2| |Divid. /8 | | /6875 | | /67 |
;+---------+ +----------+ +----------+ +--------+
;
; Constants
;
.EQU ftakt = 3685000 ; Frequency STK500 internal clock
.EQU cdivtc1 = 6875 ; Dibvider for TC1
.EQU cdiv1s = 67 ; Divider for 1 s
;
; Active Ports for LCD-Output
;
.EQU pLcdPort=PORTA ; LCD connected to PORT A
.EQU pLcdDdr=DDRA ; Datenrichtungsregister LCD-Port
;
; Benutzte Register
;
.DEF rint= R15 ; Interrupt temp register
.DEF rmp = R16 ; Multi-Purpose Register
.DEF rdiv1s = R17 ; Teiler durch 67
;
; Datensegment
;
; SRAM-Speicher für Datum und Uhrzeit
;
; Packed BCD: Z=Bit7..4, E=Bit3..0
;
; $0060 +1 +2 +3 +4 +5
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
; | Day | |Month| | Year| | Hour| |Minut| |Secnd|
; | Z E | | Z E | | Z E | | Z E | | Z E | | Z E |
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
;
.DSEG
.ORG $0060 ; Data segment begins at $0060
ramdt:
.BYTE 6 ; dd mm yy hh mm ss, reserve packed BCD
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-Vectors
;
rjmp Start ; Reset-vector
reti ; External Interrupt Request 0
reti ; External Interrupt Request 1
reti ; Timer/Counter1 Capture event
rjmp TCmp1A ; Timer/Counter1 Compare match A
reti ; Timer/Counter1 Compare match B
reti ; Timer/Counter1 Overflow
reti ; Timer/Counter0 Overflow
reti ; SPI Serial Transfer complete
reti ; Uart Rx char available
reti ; Uart Tx data register empty
reti ; Uart Tx complete
reti ; Analog comparator
;
; ************** Interrupt service routines ********
;
;
; Timer/Counter 1, Compare match A interrupt
;
TCmp1A:
in rint,SREG ; save status
inc rdiv1s ; Divider by 67, inc by one
out SREG,rint ; restore status register
reti
;
; ******** End of the Interrupt Service Routines *******
;
; ******** Some subroutines *********
;
; Include LCD-4-Bit-Routines
;
.NOLIST
.INCLUDE "Lcd4Inc.asm"
.LIST
;
; Init date-time default
;
initdt:
ldi ZH,HIGH(2*initdtt) ; Set date/time to default
ldi ZL,LOW(2*initdtt)
ldi XH,HIGH(ramdt)
ldi XL,LOW(ramdt)
ldi rmp,6
initdt1:
lpm
st X+,R0
adiw ZL,1
dec rmp
brne initdt1
ret
initdtt: ; Default date and time table
.DB 0x28,0x02,0x02,0x14,0x05,0x00 ; Packed date/time
;
; Add 1 to BCD number that Z points to
; R0 must be 0x06, R1 is used temporarily, R2 is restart
; value, rmp is maximum value for overflow
; return with carry set if no overflow occurs
;
inct:
ld R1,Z ; Read Packed BCD to R1
sec ; Set carry
adc R1,R0 ; add 06 and carry
brhs inct1 ; If half carry: don't sub 06
sub R1,R0 ; no half carry
inct1:
cp R1,rmp ; max value reached?
brcs inct2 ; no overflow
mov R1,R2 ; set to restart value
inct2:
st Z,R1 ; Write to RAM
ret ; and return
;
; Display date on LCD
;
dispdate:
clr rmp ; Set LCD home position
ldi ZH,HIGH(2*datet) ; display Date-Text
ldi ZL,LOW(2*datet)
rcall Lcd4ZTxt ; Display null-terminated string
ldi rmp,'.' ; Separator for date
mov R0,rmp
ldi ZH,HIGH(ramdt) ; Point to date
ldi ZL,LOW(ramdt)
rcall disp3 ; Display three packed BCDs
;
; Display time on LCD
;
disptime:
ldi rmp,0x40 ; LCD Cursor to start of line 2
ldi ZH,HIGH(2*timet) ; Display Time-Text
ldi ZL,LOW(2*timet)
rcall Lcd4ZTxt ; Display null-terminated string
ldi rmp,':' ; Separator for time
mov R0,rmp
ldi ZH,HIGH(ramdt+3) ; Point to time
ldi ZL,LOW(ramdt+3)
rcall disp3 ; Display three packed BCDs
lds rmp,ramdt+5 ; Read seconds
com rmp ; Invert
out PORTB,rmp ; und display on the LEDs
ret ; Fertig
;
; Strings, null-terminated, for date and time on LCD
;
datet:
.DB "Date: ",0x00,0x00
timet:
.DB "Time: ",0x00,0x00
;
; Display three packed BCDs starting at Z on the LCD
; Separator (: or .) in R0
;
disp3:
ld rmp,Z+ ; Read packed BCD 1
rcall Lcd4PBcd ; Display packed BCD
mov rmp,R0 ; Display separator
rcall Lcd4Chr
ld rmp,Z+ ; Read next packed BCD
rcall Lcd4PBcd
mov rmp,R0 ; Display separator
rcall Lcd4Chr
ld rmp,Z ; Read third packed BCD
rjmp Lcd4PBcd
;
; **************** End of the subroutines ****************
;
; ***************** Main loop starts here ****************
;
; Main program starts here
;
Start:
ldi rmp,HIGH(RAMEND) ; Initiate stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,0b00100000 ; Sleep Mode Idle
out MCUCR,rmp
ser rmp ; Port B to output, for the LEDs
out DDRB,rmp
rcall Lcd4Init ; Init LCD output
rcall initdt ; Init date and time default
rcall dispdate ; Default date/time to LCD
clr rmp
out TCNT1H,rmp ; High Byte TC1 clear
out TCNT1L,rmp ; Low Byte TC1 clear
ldi rmp,HIGH(cdivtc1) ; Compare Match, MSB first
out OCR1AH,rmp
ldi rmp,LOW(cdivtc1) ; Compare Match A, LSB last
out OCR1AL,rmp
ldi rmp,0b01000000 ; Toggle Output A on Comp Match
out TCCR1A,rmp
ldi rmp,0b00001010 ; Clear on Comp Match A, Div 8
out TCCR1B,rmp ; Start Timer
ldi rmp,0b01000000 ; TC1 CompA Int Enable
out TIMSK,rmp
sei
loop:
sleep ; sleep until int at clock
nop ; wake-up
cpi rdiv1s,cdiv1s ; 67 reached?
brcs loop ; not yet
clr rdiv1s ; New start, second has ended
ldi rmp,0x06 ; Add Packed BCD Seconds
mov R0,rmp ; Constant, needed for packed BCD
clr R2 ; Start value for overflow to upper digits
ldi rmp,0x60 ; overflow at 60 seconds
ldi ZH,HIGH(ramdt+5) ; point to SRAM-adress seconds
ldi ZL,LOW(ramdt+5)
rcall inct ; inc seconds
brcs tok ; Time is ok
sbiw ZL,1 ; set pointer to minutes
rcall inct ; inc minutes
brcs tok ; time is ok
ldi rmp,0x24 ; maximum value for hours
sbiw ZL,1 ; Point to hours
rcall inct ; inc hours
brcs tok ; time is ok
inc R2 ; Set Day/Month default to 1
ldi ZH,HIGH(ramdt+1) ; Point to month
ldi ZL,LOW(ramdt+1)
ld rmp,Z ; Read month
cpi rmp,0x02 ; February?
brne nonfeb ; Not February
adiw ZL,1 ; Point to year
ld rmp,Z ; Read year
tst rmp ; Year=00?
breq m28 ; February 2000 is 28 days only
andi rmp,0x10 ; Tens of Years=odd?
ld rmp,Z ; Read year again
brne yodd ; Tens of years odd
andi rmp,0x03 ; lower nibble year=0,4,8?
brne m28 ; February has 28 days
m29:
ldi rmp,0x30 ; February has 29 days
rjmp mok ; month is ok
yodd:
andi rmp,0x03 ; Tens of years are odd
cpi rmp,0x02 ; Lower nibble year=2 or 6?
breq m29 ; Yes, February has 29 days
m28:
ldi rmp,0x29 ; February has 28 days
rjmp mok
nonfeb:
cpi rmp,0x07 ; Month > June?
brcs monthok ; No, don't inc
dec rmp ; back one month
monthok:
andi rmp,0x01 ; Odd month?
brne m31 ; Month has 31 days
ldi rmp,0x31 ; Month has 30 days
rjmp mok
m31:
ldi rmp,0x32 ; Month has 31 days
mok:
ldi ZH,HIGH(ramdt) ; Point to day
ldi ZL,LOW(ramdt)
rcall inct ; add 1 day
brcs dok ; Date is ok
adiw ZL,1 ; Point to month
ldi rmp,0x13 ; Max monthes
rcall inct ; next month
brcs dok ; Date is ok
adiw ZL,1 ; Point to year
clr R2 ; Default year=00
rcall inct ; Next year
;
; Refresh date on LCD
;
dok:
rcall dispdate ; Display date
;
; Refresh time on LCD
;
tok:
rcall disptime ; Display time
rjmp loop
;
; End of the program
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/LCD4INCCE.html1/20/2009 8:00:36 PM
http://www.avr-asm-tutorial.net/avr_en/source/Lcd4IncCE.asm

; ***************************************************************
; * Clock with a 2-line-LCD for STK500 using Timer/Counter1 *
; * Connect the LCD over a 4-bit-data cable to the Port A *
; * Bit0=E, Bit1=RS, Bit4..7:D4..D7 *
; * Includes the LCD basic routines in Lcd4IncE.asm *
; * Adjusted to the board's clock of 3.685 MHz (STK500) *
; * (C)2002 by info@avr-asm-tutorial.net *
; * Created: 16.2.2002, Last change: 2802.2002 *
; ***************************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Timing-Scheme to create the 1-second-clock
;
;3.685.000Hz--> 460.625Hz --> 67 Hz --> 1 Hz
;
;+---------+ +----------+ +----------+ +--------+
;|CPU-Clock| |TC1-Divid.| |TC1-Compa-| |Register|
;|3,685 Mcs|-->|Prescaler |-->|re Match A|-->| rdiv1s |--> 1 s
;|7,37Mcs/2| |Divid. /8 | | /6875 | | /67 |
;+---------+ +----------+ +----------+ +--------+
;
; Constants
;
.EQU ftakt = 3685000 ; Frequency STK500 internal clock
.EQU cdivtc1 = 6875 ; Dibvider for TC1
.EQU cdiv1s = 67 ; Divider for 1 s
;
; Active Ports for LCD-Output
;
.EQU pLcdPort=PORTA ; LCD connected to PORT A
.EQU pLcdDdr=DDRA ; Datenrichtungsregister LCD-Port
;
; Benutzte Register
;
.DEF rint= R15 ; Interrupt temp register
.DEF rmp = R16 ; Multi-Purpose Register
.DEF rdiv1s = R17 ; Teiler durch 67
;
; Datensegment
;
; SRAM-Speicher für Datum und Uhrzeit
;
; Packed BCD: Z=Bit7..4, E=Bit3..0
;
; $0060 +1 +2 +3 +4 +5
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
; | Day | |Month| | Year| | Hour| |Minut| |Secnd|
;|ZE||ZE||ZE||ZE||ZE||ZE|
; +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
;
.DSEG
.ORG $0060 ; Data segment begins at $0060
ramdt:
.BYTE 6 ; dd mm yy hh mm ss, reserve packed BCD
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-Vectors
;
rjmp Start ; Reset-vector
reti ; External Interrupt Request 0
reti ; External Interrupt Request 1
reti ; Timer/Counter1 Capture event
rjmp TCmp1A ; Timer/Counter1 Compare match A
reti ; Timer/Counter1 Compare match B
reti ; Timer/Counter1 Overflow
reti ; Timer/Counter0 Overflow
reti ; SPI Serial Transfer complete
reti ; Uart Rx char available
reti ; Uart Tx data register empty
reti ; Uart Tx complete
reti ; Analog comparator
;
; ************** Interrupt service routines ********
;
;
; Timer/Counter 1, Compare match A interrupt
;
TCmp1A:
in rint,SREG ; save status
inc rdiv1s ; Divider by 67, inc by one
out SREG,rint ; restore status register
reti
;
; ******** End of the Interrupt Service Routines *******
;
; ******** Some subroutines *********
;
; Include LCD-4-Bit-Routines
;
.NOLIST
.INCLUDE "Lcd4IncE.asm"
.LIST
;
; Init date-time default
;
initdt:
ldi ZH,HIGH(2*initdtt) ; Set date/time to default
ldi ZL,LOW(2*initdtt)
ldi XH,HIGH(ramdt)
ldi XL,LOW(ramdt)
ldi rmp,6
initdt1:
lpm
st X+,R0
adiw ZL,1
dec rmp
brne initdt1
ret
initdtt: ; Default date and time table
.DB 0x28,0x02,0x02,0x14,0x05,0x00 ; Packed date/time
;
; Add 1 to BCD number that Z points to
; R0 must be 0x06, R1 is used temporarily, R2 is restart
; value, rmp is maximum value for overflow
; return with carry set if no overflow occurs
;
inct:
ld R1,Z ; Read Packed BCD to R1
sec ; Set carry
adc R1,R0 ; add 06 and carry
brhs inct1 ; If half carry: don't sub 06
sub R1,R0 ; no half carry
inct1:
cp R1,rmp ; max value reached?
brcs inct2 ; no overflow
mov R1,R2 ; set to restart value
inct2:
st Z,R1 ; Write to RAM
ret ; and return
;
; Display date on LCD
;
dispdate:
clr rmp ; Set LCD home position
ldi ZH,HIGH(2*datet) ; display Date-Text
ldi ZL,LOW(2*datet)
rcall Lcd4ZTxt ; Display null-terminated string
ldi rmp,'.' ; Separator for date
mov R0,rmp
ldi ZH,HIGH(ramdt) ; Point to date
ldi ZL,LOW(ramdt)
rcall disp3 ; Display three packed BCDs
;
; Display time on LCD
;
disptime:
ldi rmp,0x40 ; LCD Cursor to start of line 2
ldi ZH,HIGH(2*timet) ; Display Time-Text
ldi ZL,LOW(2*timet)
rcall Lcd4ZTxt ; Display null-terminated string
ldi rmp,':' ; Separator for time
mov R0,rmp
ldi ZH,HIGH(ramdt+3) ; Point to time
ldi ZL,LOW(ramdt+3)
rcall disp3 ; Display three packed BCDs
lds rmp,ramdt+5 ; Read seconds
com rmp ; Invert
out PORTB,rmp ; und display on the LEDs
ret ; Fertig
;
; Strings, null-terminated, for date and time on LCD
;
datet:
.DB "Date: ",0x00,0x00
timet:
.DB "Time: ",0x00,0x00
;
; Display three packed BCDs starting at Z on the LCD
; Separator (: or .) in R0
;
disp3:
ld rmp,Z+ ; Read packed BCD 1
rcall Lcd4PBcd ; Display packed BCD
mov rmp,R0 ; Display separator
rcall Lcd4Chr
ld rmp,Z+ ; Read next packed BCD
rcall Lcd4PBcd
mov rmp,R0 ; Display separator
rcall Lcd4Chr
ld rmp,Z ; Read third packed BCD
rjmp Lcd4PBcd
;
; **************** End of the subroutines ****************
;
; ***************** Main loop starts here ****************
;
; Main program starts here
;
Start:
ldi rmp,HIGH(RAMEND) ; Initiate stack pointer
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,0b00100000 ; Sleep Mode Idle
out MCUCR,rmp
ser rmp ; Port B to output, for the LEDs
out DDRB,rmp
rcall Lcd4Init ; Init LCD output
rcall initdt ; Init date and time default
rcall dispdate ; Default date/time to LCD
clr rmp
out TCNT1H,rmp ; High Byte TC1 clear
out TCNT1L,rmp ; Low Byte TC1 clear
ldi rmp,HIGH(cdivtc1) ; Compare Match, MSB first
out OCR1AH,rmp
ldi rmp,LOW(cdivtc1) ; Compare Match A, LSB last
out OCR1AL,rmp
ldi rmp,0b01000000 ; Toggle Output A on Comp Match
out TCCR1A,rmp
ldi rmp,0b00001010 ; Clear on Comp Match A, Div 8
out TCCR1B,rmp ; Start Timer
ldi rmp,0b01000000 ; TC1 CompA Int Enable
out TIMSK,rmp
sei
loop:
sleep ; sleep until int at clock
nop ; wake-up
cpi rdiv1s,cdiv1s ; 67 reached?
brcs loop ; not yet
clr rdiv1s ; New start, second has ended
ldi rmp,0x06 ; Add Packed BCD Seconds
mov R0,rmp ; Constant, needed for packed BCD
clr R2 ; Start value for overflow to upper digits
ldi rmp,0x60 ; overflow at 60 seconds
ldi ZH,HIGH(ramdt+5) ; point to SRAM-adress seconds
ldi ZL,LOW(ramdt+5)
rcall inct ; inc seconds
brcs tok ; Time is ok
sbiw ZL,1 ; set pointer to minutes
rcall inct ; inc minutes
brcs tok ; time is ok
ldi rmp,0x24 ; maximum value for hours
sbiw ZL,1 ; Point to hours
rcall inct ; inc hours
brcs tok ; time is ok
inc R2 ; Set Day/Month default to 1
ldi ZH,HIGH(ramdt+1) ; Point to month
ldi ZL,LOW(ramdt+1)
ld rmp,Z ; Read month
cpi rmp,0x02 ; February?
brne nonfeb ; Not February
adiw ZL,1 ; Point to year
ld rmp,Z ; Read year
tst rmp ; Year=00?
breq m28 ; February 2000 is 28 days only
andi rmp,0x10 ; Tens of Years=odd?
ld rmp,Z ; Read year again
brne yodd ; Tens of years odd
andi rmp,0x03 ; lower nibble year=0,4,8?
brne m28 ; February has 28 days
m29:
ldi rmp,0x30 ; February has 29 days
rjmp mok ; month is ok
yodd:
andi rmp,0x03 ; Tens of years are odd
cpi rmp,0x02 ; Lower nibble year=2 or 6?
breq m29 ; Yes, February has 29 days
m28:
ldi rmp,0x29 ; February has 28 days
rjmp mok
nonfeb:
cpi rmp,0x07 ; Month > June?
brcs monthok ; No, don't inc
dec rmp ; back one month
monthok:
andi rmp,0x01 ; Odd month?
brne m31 ; Month has 31 days
ldi rmp,0x31 ; Month has 30 days
rjmp mok
m31:
ldi rmp,0x32 ; Month has 31 days
mok:
ldi ZH,HIGH(ramdt) ; Point to day
ldi ZL,LOW(ramdt)
rcall inct ; add 1 day
brcs dok ; Date is ok
adiw ZL,1 ; Point to month
ldi rmp,0x13 ; Max monthes
rcall inct ; next month
brcs dok ; Date is ok
adiw ZL,1 ; Point to year
clr R2 ; Default year=00
rcall inct ; Next year
;
; Refresh date on LCD
;
dok:
rcall dispdate ; Display date
;
; Refresh time on LCD
;
tok:
rcall disptime ; Display time
rjmp loop
;
; End of the program
;

http://www.avr-asm-tutorial.net/avr_en/source/Lcd4IncCE.asm1/20/2009 8:00:38 PM
AVR-PWM-ADC-Test for STK500

Pfad: Home => AVR-overview => PWM-ADC


Tutorial for learning avr assembler language of
AVR-single-chip-processors AT90Sxxxx
of ATMEL using practical examples.
Simple 8-bit-analog-digital-converter with PWM on the STK500 board

Task
Using the analog-inputs AIN0 and AIN1 and a few hardware components, one can build up a simple AD-converter. The build-in
analog comparator is used here to compare an input voltage with a voltage produced with the timer/counter 1 (TC1) in PWM mode.
This compare voltage is adjusted, until the result is as accurate as 8 bit resolution requires. TC1 works as pulse-width modulator, the
pulse width relation determines the output voltage.
The conversion result is displayed on the LEDs of the STK500 board.

Required hardware
The picture on the left shows the whole test hardware to connect
to the STK500 board. The port pins are viewed from above the
board.
The voltage to be measured varies between 0.00 to 5.00 volt. It
is setup by the 10k potentiometer, using the board's supply
voltage, and is filtered by a 100nF. This voltages goes to the
analog comparator input AIN0, which is port PB2 on the
AT90S8515 of the STK500 board.
The compare voltage is generated by the PWM output OC1A,
which is Port PD5 of a AT90S8515 on the board. The PWM
rectangle produced by TC1 is filtered by three RC combinations
of 10k/100nF and fed into the analog comparator input AIN1,
which is port bit PB3 of the AT90S8515. That's it all.

Some further hints on that test application. The hardware


components can be placed on a small external test board.
The connections to the STK500 board can be done by
using the STK500 supplied two-wire cables, if proper pins
are mounted to the small additional board. Don't forget that
the LEDs in this test application must be connected to port
C, because we need port B for the analog inputs. Due to
this, we can't use this hard- and software for the STK200
board (which has attached the LEDs to port B by hard
wiring). After finishing work with this test setting, don't
forget to reconnect the LEDs to port B again, using the 10-
wire parallel cable, other programs might not work
correctly with the LEDs connected to port C.

To the top of that page

How it works

Generating the compare voltage by pulse-width modulation

A pulse-width-modulator generates a rectangle with a certain pulse width. This modulator holds a 1-signal for a certain time period,
the rest of the whole time period it is zero. If this rectangle signal is filtered, the pulse width produces a certain analogue voltage. If
the relation between pulse and pause of the PWM output is 50%, the voltage output is at 2.50 Volt, if it is at 25% the voltage is at
1.25 Volt, etc.

Loading and unloading of the RC filter is shown in the simulation graphic. The modulation of the PWM output by the rectangle U
(PWM) is still visible in the voltage of RC1. This modulation is strongly reduced on RC2. But U(RC2) shows a delay, its lacking
behind the mean voltage on U(RC1). This delay of the mean value is even higher on U(RC3).
If the mean value has neared its end value very closely, there are still load- and unload-swings around this mean value. The RC filter
must be dimensioned in a way that the remaining swings are well below the resolution of the AD converter. With 8 bits resolution
and 5.0 Volt operating voltage the remaining swings have to be less than 5/256 = 19.5 mV. Higher resistor and capacitor values or
adding further RC combinations reduce the voltage swings.
On the other hand, the needed time to reach the mean end value gets longer then. Therefore a PWM based ADC is not very fast (in
our case around five values per second). In practice, the compromise between delay time and remaining voltage swing should be
optimised. The time value until the voltage reaches its end value and the sensing can take place is selected by the number of
necessary PWM cycles. This number of cycles is represented by a constant in the software. In our case this software constant has
been set to 128 cycles, which is a conservative value. Without changing the software itself, the constant can be set to up to 65536
PWM cycles.
To play around with selecting R and C values, simulating load- and unload cycles, and selecting optimised cycle values, a small
Pascal program was devellopped. After compilation it runs on a command line. The source code avr_pwm1.pas can be compiled
with a compiler to yield an executable.
The frequency that the PWM runs with, can be calculated for 8 bits resolution as

f (PWM) = clockfrequency / 510 (9 bit: 1022, 10 bit: 2046)

At a clock frequency of 3.685 Mcs/s on the STK500 board we yield 7,225.5 cs/s or 138.4 microseconds per PWM cycle. If we wait
for 128 cycles for settlement of the mean voltage before sensing and 8 bit resolution, the conversion time is around 142 milliseconds
per measurement or seven measurements per second. Not very fast, but even faster than a man's eye.

Reference value of this circuitry is the operating voltage of the processor. This refence voltage can be adjusted with the studio
software supplied with the STK500. The accuracy of the PWM signal in the lower range from 0.00 to 0.10 V, but even more in the
most upper range, is limited, because the MOS output drivers do not reach exactly the operating voltage bounds. This causes some
inaccuracy in the midrange and some non-linearity at the upper and lower bound of the operating voltage. Therefore it doesn't make
much sense to design this software for 9 or 10 bits resolution. If you need more accurate values, use a processor with built-in ADC.

To the top of that page

The method of sukzessive approximation

To measure the input voltage, we could step up with the pulse width of the comparation voltage and stop this increase, if the
comparision voltage is higher than the voltage on the measuring input pin. At 8 bit resolution, this would require up to 255 steps, at
10 bit resolution up to 1,023 steps.
To speed this up, the conversion method of sukzessive approximation is applied. In the first step the comparator voltage is set to half
of the operating voltage, 2.50 Volt. It is determined, if the input voltage is higher or lower than this. If the input voltage is lower, the
next comparator voltage is set to 1.25 Volt. If is is higher, the next comparator value is set to 3.75 V. This step is repeated, until we
know exact enough, how high the input voltage is. At 8 bits resolution we need to make eight steps, at 10 bits ten steps. This is by a
factor of 30 resp. 100 faster than the stepwise increase of the comparator value.
This algorithm can be programmed very easily. The fist five steps for an 8 bit conversion are shown in the table. The table lists the
comparator voltages at step n and the corresponding value of the 8-bit PWM. If the comparator is higher than the measuring input,
the next value is in the upper row of the table. Vice versa, if its smaller.
1 2 3 4 5
1000.0000 0100.0000 0010.0000 0001.0000 0000.1000
V=0,15625V
V=0,3125V 0000.1000
0001.0000 V=0,46875V
V=0,625V 0001.1000
0010.0000 V=0,78125V
V=0,9375V 0010.1000
0011.0000 V=1,09375V
V=1,25V 0011.1000
0100.0000 V=1,40625V
V=1,5625V 0100.1000
0101.0000 V=1,71875V
V=1,875V 0101.1000
0110.0000 V=2,03125V
V=2,1875V 0110.1000
0111.0000 V=2,34375V
V=2,5V 0111.1000
1000.0000 V=2,65625V
V=2,8125V 1000.1000
1001.0000 V=2,96875V
V=3,125V 1001.1000
1010.0000 V=3,28125V
V=3,4375V 1010.1000
1011.0000 V=3,59375V
V=3,75V 1011.1000
1100.0000 V=3,90625V
V=4,0625V 1100.1000
1101.0000 V=4,21875V
V=4,375V 1101.1000
1110.0000 V=4,53125V
V=4,6875V 1110.1000
1111.0000 V=4,84375V
1111.1000
The steps are easy: at every step of the approximation the appropriate bit is first set to one. If the voltage of the PWM is too high,
this bit is set to zero in the next step. Easy to program!

To the top of that page

Software
The software is available in HTML format ADC8.html and as ASM source code file ADC8.asm.

The program spents very long times waiting for the PWM to settle for the mean value of the RC filter. This is ideal for using
interrupts, because otherwise we would have to program very long and complicated timing loops. Because TC1 has nothing else to
do than generating the PWM signal by counting up and down, we can use it for our whole timing too. The processor itself remains
sleeping the whole time, and is woken up every 142 microseconds, when TC1 places an interrupt. After woken up and worked
through the interrupt routine of TC1, the processor checks the ADC-ready flag. If it is not set, the processor goes back to sleep again.
If the flag is set, the result is displayed on the LED output port and the flag is cleared.

Main program

The main program runs the following steps:

1. The stack is set up. This is necessary because the program uses timer interrupts. Interrupts use the stack to store their return
address on the stack. The stack is located and set up on the top of the SRAM space.
2. The cycle counter is set. The cycle counter determines the number of cycles of the PWM before the sensing of the
comparision between the PWM-generated voltage and the analog input takes place. In the example, 128 cycles are selected as
constant. Change the constant CycLen0, if you want to set the resampling rate to other values (e.g. to one measurement per
second).
3. The bit counter rBlc is set to 0x80 at the beginning of a measuring cycle. This results in a comparator voltage of 2.50 V as
comparator voltage. The temporary result rTmp is set to that value accordingly.
4. The port outputs of port C are selected as outputs to drive the LEDs.
5. Port bit PD5 of port D is selected as output, because it generates the PWM output signal on this pin.
6. The sleep mode is set to the idle mode. This allows the processor to react to the SLEEP instruction and to wake up on
interrupts by TC1.
7. Timer/Counter 1 is set up as 8-bit-PWM, its clock input is connected to the processor clock, no prescaling takes place to yield
the highest possible PWM clock rate.
8. PWM pulse width is set to 50% (0x0080).
9. The Timer Int Mask Register TIMSK is set to allow TC1 overflow interrupts, so that TC1 causes an interrupt each time that
the PWM cycle has reached its end.
10. The general interrupt flag of the processor is set to one to allow interrupts.

Now the loop starts, which is ran through each time the TC1 overflow interrupt wakes up the processor. After running through the
vectored int routine the ready-flag is asked, if the AD conversion has ended and the result value is valid. If this is the case, the flag is
cleared, the ADC result is inverted bitwise and the byte is outputted to the LEDs. Then the processor is set to sleep again, until the
ready-flag is set after wake-up.

To the top of that page

Interrupt processing

Central routine of the AD conversion is the pulse width generator of timer/counter 1. Each time TC1 has reached its cycle end the
overflow interrupt is generated, the program counter is copied to the stack and program execution jumps to the interrupt vector. This
routine does all the necessary control of the PWM-ADC and sets the ready-flag on return, if the AD conversion is ready. After
conversion, the next measuring cycle is automatically restarted. By selecting the PWM cycle numbers as constants on the top of the
program, the repeating frequency of the measurements and the delay before sensing the different bits can be adjusted.
The graphic left shows the algorithm for the whole control of the AD
conversion.
The int vector routine starts with saving the content of the processor's
status register. Prior to returning from the interrupt, the original content
of the register is restored.
In the next step the cycle counter is decreased by one. If this cycle
counter reaches zero, the comparator voltage generated by the PWM and
filtered by the RC filter has reached its mean value. If the cycle counter
is not zero, further cycles have to be ran through and the interrupt vector
routine ends.
If the necessary number of PWM cycles has been waited for, the PWM
cycle counter is set to the constant value. Then the analog comparator
output is asked for the result of the comparision. If the PWM generated
comparation value is higher than the input voltage, the actual bit,
represented by the value in rBlc, in rTmp is cleared. If not, then this
actual bit remains one.
Now the bit counter rBlc with the actual bit is shifted right one bit. By
this instruction a zero enters rBlc from the left, and the content of the bit
0 is shifted to the carry flag in the status register. If a zero rolls out to
carry, the conversion has not reached its end and the sukzessive
approximation has to repeat for the next bit.
If a one rolls out of the bit counter, the conversion is ready. The result in
the temporary result register is copied to the result register, the ready-
flag in the flag register is set, the PWM cycle counter is set to the
constant value that has been defined for the sensing of the highest bit,
the temporary result register is cleared and the bit counter is set to $80
(for the next conversion).
The currently active bit in rBlc is copied to the temporary result register
(set active bit to one), and the current temporary value is copied to the
timer/counter's compare register in order to adjust the comparision
voltage on the AIN1 input of the comparator.
At the end of the interrupt routine, the status register gets back its
original content, and the interrupt routine returns.

The whole interrupt routine requires less than 25 clock cycles or 6 microseconds, and is very short. If there would be other tasks for
the processor, this wouldn't be a serious delay.

Changes and possible extensions

If you'd like to experiment with 9 or 10 bit resolution instead: The result register, the temporary result register and the bit counter
need to be designed using words (two registers each), the result doesn't fit to the eight LEDs (decide which bits to display).
If you like to convert the result to its decimal form and display the result on an LCD display or send it over the serial transmitter to a
computer: use the fixed point conversion routine provided in the calculation section of the beginner's course.

To the top of that page

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_ADC500.html1/20/2009 8:00:41 PM
8-<A HREF="beginner/CALC.html#Bits">bit</A>-<A HREF="beginner/PDETAIL.html#ANALOG">Analog</A>-to-Digital-Converter

Pfad: Home => AVR-overview => 8-bit-ADC with STK500 => adc8 software

Assembler source code for the conversion of


an analogue voltage to an 8-bit-number
; +-----------------------------------------------------+
; | 8-Bit-Analog-Digital-Converter for ATMEL AT90S8515 |
; | on the STK500 board, Output by LEDs |
; | (C)2003 by http://www.avr-asm-tutorial.net |
; | Used ports: |
; | Output PWM pulse = OC1A on Port D, Bit 5, via |
; | triple RC-filter to |
; | Inverted analog input AIN1 on Port B Bit 3, |
; | Non-inverted analog input AIN0 on Port B Bit 2 |
; | connected to voltage to be measured |
; | Output Port C connected to LEDs displays result |
; +-----------------------------------------------------+
;
; Written for and tested with AT90S8515 on STK500
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU CycLen = 128 ; Number of PWM-cycles to filter before sensing
.EQU CycLen0 = 128 ; Number of PWM-cycles before first sensing
;
; Register
;
.DEF rRes = R1 ; final value of the ADC
.DEF rTmp = R14 ; Temporary value for ADC
.DEF rSrg = R15 ; Temporary register für SREG interim storage in
ints
.DEF rmp = R16 ; Universal register outside ints
.DEF rimp = R17 ; Universal register within ints
.DEF rFlg = R18 ; Flag register, Bit 0 = ADC ready
.DEF rBlc = R19 ; Bit-level-counter for ADC
.DEF rCcL = R24 ; Cycle counter for ADC, LSB
.DEF rCcH = R25 ; dto., MSB
;
; Reset- and Interrupt-vectors
;
rjmp main ; Reset
reti ; INT0
reti ; INT1
reti ; TC1-Capt
reti ; TC1-CompA
reti ; TC1-CompB
rjmp Tc1Ovflw ; TC1-Ovflw
reti ; TC0-Ovflw
reti ; SPI STC
reti ; UART RX
reti ; UART UDRE
reti ; UART TX
reti ; Ana-Comp
;
; TC1-Overflow on each PWM-cycle end
;
Tc1Ovflw:
in rSrg,SREG ; Save SREG
sbiw rCcL,1 ; decrement cycle counter word
brne Tc1OvflwR ; if word<>0: int ready
ldi rCcH,HIGH(CycLen) ; Set cycle counter for next bit
ldi rCcL,LOW(CycLen)
sbis ACSR,ACO ; check analogue comparator output
eor rTmp,rBlc ; voltage too high, clear last bit
lsr rBlc ; shift active bit one position right
brcc Tc1OvflwA ; if carry<>0: not ready yet
mov rRes,rTmp ; copy the result
sbr rFlg,0x01 ; set ready-flag
ldi rCcH,HIGH(CycLen0) ; set cycle counter for restart
ldi rCcL,LOW(CycLen0)
clr rTmp ; clear result
ldi rBlc,0x80 ; set bit counter
Tc1OvflwA:
or rTmp,rBlc ; set next bit to one
clr rimp ; set TC1-PWM pulse width
out OCR1AH,rimp ; high byte first!
out OCR1AL,rTmp ; then low byte!
Tc1OvflwR: ; return from Int
out SREG,rSrg ; restore SREG to original content
reti ; set int flag, return
;
; Main program loop
;
main:
ldi rmp,HIGH(RAMEND) ; define stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rCcH,HIGH(CycLen0) ; set cycle length before first
measurement
ldi rCcL,LOW(CycLen0)
ldi rBlc,0x80 ; set bit counter to highest bit value
mov rTmp,rBlc ; clear result
ldi rmp,0xFF ; port C all bits output, drives LEDs
out DDRC,rmp ; all data direction bits = 1
sbi DDRD,PD5 ; PWM-output bit OC1A as output pin
ldi rmp,0b00100000 ; define sleep-mode idle
out MCUCR,rmp
ldi rmp,0b10000001 ; TC1 as 8-bit-PWM, non-invertet
out TCCR1A,rmp ; to TC1 control register A
ldi rmp,0b00000001 ; TC1-clock = system clock
out TCCR1B,rmp ; to TC1 control register B
clr rmp ; puls-width of PWM to $0080
out OCR1AH,rmp ; first the HIGH byte!
ldi rmp,0x80 ; then the LOW byte!
out OCR1AL,rmp
ldi rmp,0b10000000 ; TC1 overflow interrupt enable
out TIMSK,rmp ; to Timer Int Mask Register
sei ; enable CPU reaction to interrupts
;
; Main loop
;
main1:
sleep ; CPU sleeps
nop ; dummy instruction, loaded before sleep
sbrs rFlg,0 ; check ready flag bit 0 if ADC is ready
rjmp main1 ; not ready, sleep on
cbr rFlg,0x01 ; clear ready bit 0
mov rmp,rRes ; copy result of ADC
com rmp ; invert all bits (LED active low)
out PortC,rmp ; to LED port
rjmp main1 ; done, go to sleep again
;
; End of program
;

©2003 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/ADC8.html1/20/2009 8:00:47 PM
http://www.avr-asm-tutorial.net/avr_en/source/ADC8.asm

; +-----------------------------------------------------+
; | 8-Bit-Analog-Digital-Converter for ATMEL AT90S8515 |
; | on the STK500 board, Output by LEDs |
; | (C)2003 by http://www.avr-asm-tutorial.net |
; | Used ports: |
; | Output PWM pulse = OC1A on Port D, Bit 5, via |
;| triple RC-filter to |
; | Inverted analog input AIN1 on Port B Bit 3, |
; | Non-inverted analog input AIN0 on Port B Bit 2 |
;| connected to voltage to be measured |
; | Output Port C connected to LEDs displays result |
; +-----------------------------------------------------+
;
; Written for and tested with AT90S8515 on STK500
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU CycLen = 128 ; Number of PWM-cycles to filter before sensing
.EQU CycLen0 = 128 ; Number of PWM-cycles before first sensing
;
; Register
;
.DEF rRes = R1 ; final value of the ADC
.DEF rTmp = R14 ; Temporary value for ADC
.DEF rSrg = R15 ; Temporary register für SREG interim storage in ints
.DEF rmp = R16 ; Universal register outside ints
.DEF rimp = R17 ; Universal register within ints
.DEF rFlg = R18 ; Flag register, Bit 0 = ADC ready
.DEF rBlc = R19 ; Bit-level-counter for ADC
.DEF rCcL = R24 ; Cycle counter for ADC, LSB
.DEF rCcH = R25 ; dto., MSB
;
; Reset- and Interrupt-vectors
;
rjmp main ; Reset
reti ; INT0
reti ; INT1
reti ; TC1-Capt
reti ; TC1-CompA
reti ; TC1-CompB
rjmp Tc1Ovflw ; TC1-Ovflw
reti ; TC0-Ovflw
reti ; SPI STC
reti ; UART RX
reti ; UART UDRE
reti ; UART TX
reti ; Ana-Comp
;
; TC1-Overflow on each PWM-cycle end
;
Tc1Ovflw:
in rSrg,SREG ; Save SREG
sbiw rCcL,1 ; decrement cycle counter word
brne Tc1OvflwR ; if word<>0: int ready
ldi rCcH,HIGH(CycLen) ; Set cycle counter for next bit
ldi rCcL,LOW(CycLen)
sbis ACSR,ACO ; check analogue comparator output
eor rTmp,rBlc ; voltage too high, clear last bit
lsr rBlc ; shift active bit one position right
brcc Tc1OvflwA ; if carry<>0: not ready yet
mov rRes,rTmp ; copy the result
sbr rFlg,0x01 ; set ready-flag
ldi rCcH,HIGH(CycLen0) ; set cycle counter for restart
ldi rCcL,LOW(CycLen0)
clr rTmp ; clear result
ldi rBlc,0x80 ; set bit counter
Tc1OvflwA:
or rTmp,rBlc ; set next bit to one
clr rimp ; set TC1-PWM pulse width
out OCR1AH,rimp ; high byte first!
out OCR1AL,rTmp ; then low byte!
Tc1OvflwR: ; return from Int
out SREG,rSrg ; restore SREG to original content
reti ; set int flag, return
;
; Main program loop
;
main:
ldi rmp,HIGH(RAMEND) ; define stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rCcH,HIGH(CycLen0) ; set cycle length before first measurement
ldi rCcL,LOW(CycLen0)
ldi rBlc,0x80 ; set bit counter to highest bit value
mov rTmp,rBlc ; clear result
ldi rmp,0xFF ; port C all bits output, drives LEDs
out DDRC,rmp ; all data direction bits = 1
sbi DDRD,PD5 ; PWM-output bit OC1A as output pin
ldi rmp,0b00100000 ; define sleep-mode idle
out MCUCR,rmp
ldi rmp,0b10000001 ; TC1 as 8-bit-PWM, non-invertet
out TCCR1A,rmp ; to TC1 control register A
ldi rmp,0b00000001 ; TC1-clock = system clock
out TCCR1B,rmp ; to TC1 control register B
clr rmp ; puls-width of PWM to $0080
out OCR1AH,rmp ; first the HIGH byte!
ldi rmp,0x80 ; then the LOW byte!
out OCR1AL,rmp
ldi rmp,0b10000000 ; TC1 overflow interrupt enable
out TIMSK,rmp ; to Timer Int Mask Register
sei ; enable CPU reaction to interrupts
;
; Main loop
;
main1:
sleep ; CPU sleeps
nop ; dummy instruction, loaded before sleep
sbrs rFlg,0 ; check ready flag bit 0 if ADC is ready
rjmp main1 ; not ready, sleep on
cbr rFlg,0x01 ; clear ready bit 0
mov rmp,rRes ; copy result of ADC
com rmp ; invert all bits (LED active low)
out PortC,rmp ; to LED port
rjmp main1 ; done, go to sleep again
;
; End of program
;

http://www.avr-asm-tutorial.net/avr_en/source/ADC8.asm1/20/2009 8:00:52 PM
R/2R-network as DAC for an AVR

Path: Home => AVR-overview => R/2R-DAC

Tutorial for learning avr


assembler language of
AVR-single-chip-
processors AT90Sxxxx
of ATMEL using practical
examples.

Simple 8-bit-digital-
to-analog-converter
using a R/2R-network

Task
A conversion of digital values to an analogue voltage can be performed using an integrated circuit. A cheaper and less
sophisticated method is a R/2R-network, followed by an opamp.

A R/2R-network is made of resistors like shown in the picture. The


bits, either at 0 or the operating voltage, enter the network via a
resistor of a double value than the rest of the network. Each bit
contributes its part to the resulting voltage on the output. Believe it
or not, this works fine. The commercial Digital-to-Analog-
Converters have those resistor networks within their integrated
circuits.

The output of an AVR port doesn't drive much current, if its voltages
should stay near either ground or the operating voltage. So, the
resistors should be above several tens of kilo-ohms. Because these
networks do not provide much current, an opamp decouples the
R/2R-network from the following rest of the circuit.

The resistor values should be as accurate as the whole network is


expected to be accurate. Deviations are especially relevant for the
higher bits. The following table shows some stepwise increases in
the output voltage of a R/2R-network when using a 51/100k
combination of resistors. (Calculations were made with a Free-
Pascal program, free source code can be downloaded from here).

R2R-network calculation tool, (C)2004 info!at!avr-asm-tutorial.net


------------------------------------------------------------------
N bits resolution: nr=8[bits], Bits=00000000
Voltages: ub=5.000[V], ul=0.000[V], uh=5.000[V]
Resistors: R1= 51k0, R2=100k0

Input combinations and output voltages


00000000: 0.000[V]
00000001: 0.019[V] (Delta= 18.69[mV])
00000010: 0.038[V] (Delta= 19.06[mV])
00000011: 0.056[V] (Delta= 18.69[mV])
00000100: 0.076[V] (Delta= 19.62[mV])
00000101: 0.095[V] (Delta= 18.69[mV])
00000110: 0.114[V] (Delta= 19.06[mV])
00000111: 0.132[V] (Delta= 18.69[mV])
00001000: 0.153[V] (Delta= 20.67[mV])
00001001: 0.172[V] (Delta= 18.69[mV])
00001010: 0.191[V] (Delta= 19.06[mV])
00001011: 0.210[V] (Delta= 18.69[mV])
00001100: 0.229[V] (Delta= 19.62[mV])
00001101: 0.248[V] (Delta= 18.69[mV])
00001110: 0.267[V] (Delta= 19.06[mV])
00001111: 0.286[V] (Delta= 18.69[mV])
00010000: 0.308[V] (Delta= 22.72[mV])
00010001: 0.327[V] (Delta= 18.69[mV])
00010010: 0.346[V] (Delta= 19.06[mV])
00010011: 0.365[V] (Delta= 18.69[mV])
00010100: 0.384[V] (Delta= 19.62[mV])
00010101: 0.403[V] (Delta= 18.69[mV])
00010110: 0.422[V] (Delta= 19.06[mV])
00010111: 0.441[V] (Delta= 18.69[mV])
00011000: 0.462[V] (Delta= 20.67[mV])
...
01111110: 2.446[V] (Delta= 19.06[mV])
01111111: 2.465[V] (Delta= 18.69[mV])
10000000: 2.517[V] (Delta= 51.72[mV])
10000001: 2.535[V] (Delta= 18.69[mV])
10000010: 2.554[V] (Delta= 19.06[mV])
10000011: 2.573[V] (Delta= 18.69[mV])
...

Note the extraordinary step in voltage when Bit 7 goes from low to high! It jumps up more than two ordinary steps. This
might be unacceptable for an 8-bit-network, but its fine for a four-bit-network.

Required hardware
The hardware is easy to built, it is a real resistor grave-yard.

The CA3140 is an opamp with a FET stage on the input, that can be driven down to the negative operating voltage. You
might use a 741 opamp instead, but the consequences are discucssed below.
The operating voltage of 5 Volt here is taken from the 10-pin-connector. This connector fits to a STK200 or STK500
board. It is also possible to feed the opamp by a higher voltage, which has some advantages (see below).
Instead of two parallel resitors, you can use resistors that have approximately half the value of 100k, e.g. 51k. As the
network has a resolution of 256, this brings some inaccuracy, see above.

To the top of that page

Applying the R/2R-network

Generating a sawtooth

The following program produces a sawtooth voltage on the output of the R/2R-network. The source code is available for
download here.

; **************************************************************
; * R/2R-Network produces a sawtooth signal on Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
sawtooth:
out PORTD,rmp
inc rmp
rjmp sawtooth

The result is somewhat surprising. Doesn't look like a sawtooth but like a
saw that has done some efforts in cutting steel.

The reason for this is not the R/2R-network but the opamp. He doesn't
work fine at the upper bounds of the operating voltage.

So we have to limit the output of the R/2R-network to approximately 2.5 Volts. This is done by software (source code to
be downloaded here).

; **************************************************************
; * R/2R-Network produces a sawtooth signal on Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
sawtooth:
out PORTD,rmp
inc rmp
andi rmp,0x7F ; set bit 7 to zero
rjmp sawtooth

That looks much better now.

Note that we would not need Bit 7 of the port now, it can be tied to
ground, as it is always low.

Here's the result of exchanging the CA3140 buffer to a cheaper 741


opamp. The 741 is neither operating near the operating voltage nor does he
work near ground. So the voltages of our R/2R-network would have to be
limited from a minimum of approximately 2 Volts to a maximum of 4
Volts.

To the top of that page

Generating a triangle

Generating a triangle is a similiarly easy task: just counting up and down. The source code can be downloaded here. It
allows adjusting the frequency by changing the value of the constants "delay" and the upper bound by adjusting the
constant "maxAmp".

; **************************************************************
; * R/2R-Network produces a triangle signal on Port D *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
.DEF rdl = R17 ; Delay counter
;
; Constants
;
.EQU maxAmp = 127 ; Maximum amplitude setting
.EQU delay = 1 ; Delay, higher value causes lower frequency
;
; Main program start
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
triangle:
clr rmp
loopup:
out PORTD,rmp ; to port
ldi rdl,delay
delayup:
dec rdl
brne delayup
inc rmp ; next higher value
cpi rmp,maxAmp
brcs loopup
loopdwn:
out PORTD,rmp
ldi rdl,delay
delaydwn:
dec rdl
brne delaydwn
dec rmp
brne loopdwn
rjmp triangle ; and again forever

To the left, the voltage is


limited to 2.5 V, to the right
it's the full 5.0 V.

To the top of that page

Generating a sinewave

At last we need the famous sinewave. If you think that I'll program a sine function generator for that in assembler, you're
wrong. I'll let this do the PC in Pascal (by use of the small free-pascal program that can be downloaded here) and include
the resulting sinewave table (download here) to my program (download here.

; **************************************************************
; * Produces a sinewave on a R/2R-network connected to PORTD *
; * (C)2005 by avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
; Start of program source code
;
ldi rmp,0xFF ; Set all pins of port D to be output
out DDRD,rmp
ldi ZH,HIGH(2*SineTable) ; Point Z to Table in flash
ldi ZL,LOW(2*SineTable)
clr rmp
loop1:
nop
nop
nop
loop2:
lpm ; Read from table
out PORTD,R0 ; Write value to port D
adiw ZL,1 ; point to next value
dec rmp ; End of Table reached
brne loop1
ldi ZH,HIGH(2*SineTable) ; Point Z to Table in flash
ldi ZL,LOW(2*SineTable)
rjmp loop2
;
; End of source code
;
; Include sinewave table
;
.INCLUDE "sine8_25.txt"
;
; End of program
;
;
; Sinewave table for 8 bit D/A
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (generated by sinewave.pas)
;
Sinetable:
.DB 64,65,67,68,70,72,73,75
.DB 76,78,79,81,82,84,85,87
.DB 88,90,91,92,94,95,97,98
.DB 99,100,102,103,104,105,107,108
.DB 109,110,111,112,113,114,115,116
.DB 117,118,118,119,120,121,121,122
.DB 123,123,124,124,125,125,126,126
.DB 126,127,127,127,127,127,127,127
.DB 128,127,127,127,127,127,127,127
.DB 126,126,126,125,125,124,124,123
.DB 123,122,121,121,120,119,118,118
.DB 117,116,115,114,113,112,111,110
.DB 109,108,107,105,104,103,102,100
.DB 99,98,97,95,94,92,91,90
.DB 88,87,85,84,82,81,79,78
.DB 76,75,73,72,70,68,67,65
.DB 64,62,61,59,58,56,54,53
.DB 51,50,48,47,45,44,42,41
.DB 39,38,36,35,34,32,31,30
.DB 28,27,26,25,23,22,21,20
.DB 19,18,17,15,14,13,13,12
.DB 11,10,9,8,8,7,6,5
.DB 5,4,4,3,3,2,2,2
.DB 1,1,1,0,0,0,0,0
.DB 0,0,0,0,0,0,1,1
.DB 1,2,2,2,3,3,4,4
.DB 5,5,6,7,8,8,9,10
.DB 11,12,13,13,14,15,17,18
.DB 19,20,21,22,23,25,26,27
.DB 28,30,31,32,34,35,36,38
.DB 39,41,42,44,45,47,48,50
.DB 51,53,54,56,58,59,61,62

That's all. It produces a nice sine. You wouldn't expect here to be a digital
AVR at work but a nice and clean LC-oscillator.

Unfortunately this method cannot be applied to produce sinewaves with


more than 1,800 cycles/s, because 4 Mcs/s divided by 256 is only 15,625.
And you need at least some clock cycles in between to read from the
sinewave table.

To the top of that page

Playing musical notes with the R/2R network

The following program uses the R/2R network to play musical notes with the keyboard. It works without changes on a
STK200 board with a 4 Mcs/s 8515, with the eight keys connected to port D and the R/2R network connected to port B
(download here).

; ******************************************************************
; * Music on an STK200, using a R/2R network for playing tunes *
; * PortD has eight keys (active low), PortB generates the *
; * output for the R/2R-network, plays notes when key is activated *
; * ATMEL AT90S8515 at 4 Mcs/s *
; * (C)2005 by info!at!avr-asm-tutorial.net *
; ******************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU clock = 4000000 ; processor clock
.EQU cNSine = 32 ; Table length of sine wave
;
.DEF rLen = R1 ; length of delay for the sine wave
.DEF rCnt = R2 ; Counter for length delay
.DEF rmp = R16 ; multi purpose register
.DEF rTab = R17 ; counter for table length
;
ldi rmp,0xFF ; all bits of port B = output => R/2R network
out DDRB,rmp ; set data direction register
wtloop:
in rmp,PIND ; read the keys
cpi rmp,0xFF ; all keys inactive?
breq wtloop ; yes, wait until active
ldi ZH,HIGH(2*MusicTable) ; Point Z to music table
ldi ZL,LOW(2*MusicTable)
tabloop:
rol rmp ; rotate next lowest bit into carry
brcc tabfound ; found that key pressed
adiw ZL,1 ; point Z to next table value
rjmp tabloop ; check next bit
tabfound:
lpm ; read music table value to R0
mov rlen,R0 ; copy to delay, R0 used otherwise
;
; Play a tone until all keys are inactive
;
startsine:
ldi ZH,HIGH(2*SineTable) ; Set Z to sine wave table
ldi ZL,LOW(2*SineTable)
ldi rTab,cNSine ; Length of SineWave table
;
; The following code is optimized for reaching equal runtimes
; for all loop runs, clocks cycles needed are calculated
; for all instructions after their execution,
; clock cycles during table read / clock cycles at table end
;
loopsine:
in rmp,PIND ; 1/- Check if input still active
cpi rmp,0xFF ; 2/-
breq wtloop ; 3/- key not active any more, restart
nop ; 4/- delay to synchronize
loopnext:
lpm ; 7/3 read sinewave value to R0
out PORTB,R0 ; 8/4 copy to R/2R network
mov rCnt,rLen ; 9/5 Set delay counter value
; delay loop, requires 3*rLen-1 clock cycles
loopdelay:
dec rCnt ; (1) next counter value
brne loopdelay ; (2/1) not yet zero
; 3*rLen+8/3*rLen+4 at end of delay loop
adiw ZL,1 ; 3*rLen+10/3*rLen+6 next value in table
dec rTab ; 3*rLen+11/3*rLen+7 table counter
brne loopsine ; 3*rLen+13/3*rLen+8 play next value in table
ldi ZH,HIGH(2*SineTable) ; -/3*rLen+9 reload first table value
ldi ZL,LOW(2*SineTable) ; -/3*rLen+10
ldi rTab,cNSine ; -/3*rLen+11 Length of sine wave table
rjmp loopnext ; -/3*rLen+13 restart loop
;
; Table for delays to generate the 8 different frequencies
;
; frequency = clock / TableLength / ( 3 * rLen + 13 )
; rLen = ( clock /TableLength / frequency - 13 ) / 3
;
MusicTable:
; f=261.6 293.7 329.6 349.2 392.0 440.0 493.9 523.2 (should be)
.DB 155, 138, 122, 115, 102, 90, 80, 75
; f=261.5 292.7 329.8 349.2 391.9 441.7 494.1 525.2 (is really)
; differences caused by rounding and the limited resolution)
;
; Sinewave table for 8 bit D/A
; Table length = 32 values
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (generated by sinewave.pas)
;
Sinetable:
.DB 64,76,88,99,109,117,123,126
.DB 128,126,123,117,109,99,88,76
.DB 64,51,39,28,19,11,5,1
.DB 0,1,5,11,19,28,39,51
;
; End of program
;

Of cource, you need to attach a small speaker or an earphone to the buffer output. Otherwise the nice sinewaves remain
silent.

To the top of that page

©2005 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_DAC.html1/20/2009 8:00:55 PM
http://www.avr-asm-tutorial.net/avr_en/source/SAWTOOTH1.asm

; **************************************************************
; * R/2R-Network produces a sawtooth signal on Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
sawtooth:
out PORTD,rmp
inc rmp
rjmp sawtooth

http://www.avr-asm-tutorial.net/avr_en/source/SAWTOOTH1.asm1/20/2009 8:00:59 PM
http://www.avr-asm-tutorial.net/avr_en/source/SAWTOOTH2.asm

; **************************************************************
; * R/2R-Network produces a sawtooth signal on Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
sawtooth:
out PORTD,rmp
inc rmp
andi rmp,0x7F ; set bit 7 to zero
rjmp sawtooth

http://www.avr-asm-tutorial.net/avr_en/source/SAWTOOTH2.asm1/20/2009 8:01:00 PM
http://www.avr-asm-tutorial.net/avr_en/source/TRIANGLE.asm

; **************************************************************
; * R/2R-Network produces a triangle signal on Port D *
; * (C)2005 by info@avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
.DEF rdl = R17 ; Delay counter
;
; Constants
;
.EQU maxAmp = 127 ; Maximum amplitude setting
.EQU delay = 1 ; Delay, higher value causes lower frequency
;
; Main program start
;
ldi rmp,0xFF; Set all pins of Port D as output
out DDRD,rmp
triangle:
clr rmp
loopup:
out PORTD,rmp ; to port
ldi rdl,delay
delayup:
dec rdl
brne delayup
inc rmp ; next higher value
cpi rmp,maxAmp
brcs loopup
loopdwn:
out PORTD,rmp
ldi rdl,delay
delaydwn:
dec rdl
brne delaydwn
dec rmp
brne loopdwn
rjmp triangle ; and again forever

http://www.avr-asm-tutorial.net/avr_en/source/TRIANGLE.asm1/20/2009 8:01:01 PM
http://www.avr-asm-tutorial.net/avr_en/source/sine8_25.txt

;
; Sinewave table for 8 bit D/A
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (generated by sinewave.pas)
;
Sinetable:
.DB 64,65,67,68,70,72,73,75
.DB 76,78,79,81,82,84,85,87
.DB 88,90,91,92,94,95,97,98
.DB 99,100,102,103,104,105,107,108
.DB 109,110,111,112,113,114,115,116
.DB 117,118,118,119,120,121,121,122
.DB 123,123,124,124,125,125,126,126
.DB 126,127,127,127,127,127,127,127
.DB 128,127,127,127,127,127,127,127
.DB 126,126,126,125,125,124,124,123
.DB 123,122,121,121,120,119,118,118
.DB 117,116,115,114,113,112,111,110
.DB 109,108,107,105,104,103,102,100
.DB 99,98,97,95,94,92,91,90
.DB 88,87,85,84,82,81,79,78
.DB 76,75,73,72,70,68,67,65
.DB 64,62,61,59,58,56,54,53
.DB 51,50,48,47,45,44,42,41
.DB 39,38,36,35,34,32,31,30
.DB 28,27,26,25,23,22,21,20
.DB 19,18,17,15,14,13,13,12
.DB 11,10,9,8,8,7,6,5
.DB 5,4,4,3,3,2,2,2
.DB 1,1,1,0,0,0,0,0
.DB 0,0,0,0,0,0,1,1
.DB 1,2,2,2,3,3,4,4
.DB 5,5,6,7,8,8,9,10
.DB 11,12,13,13,14,15,17,18
.DB 19,20,21,22,23,25,26,27
.DB 28,30,31,32,34,35,36,38
.DB 39,41,42,44,45,47,48,50
.DB 51,53,54,56,58,59,61,62

http://www.avr-asm-tutorial.net/avr_en/source/sine8_25.txt1/20/2009 8:01:05 PM
http://www.avr-asm-tutorial.net/avr_en/source/SINEWAVE.asm

; **************************************************************
; * Produces a sinewave on a R/2R-network connected to PORTD *
; * (C)2005 by avr-asm-tutorial.net *
; **************************************************************
;
.INCLUDE "8515def.inc"
;
; Register definitions
;
.DEF rmp = R16 ; Multipurpose register
;
; Start of program source code
;
ldi rmp,0xFF ; Set all pins of port D to be output
out DDRD,rmp
ldi ZH,HIGH(2*SineTable) ; Point Z to Table in flash
ldi ZL,LOW(2*SineTable)
clr rmp
loop1:
nop
nop
nop
loop2:
lpm ; Read from table
out PORTD,R0 ; Write value to port D
adiw ZL,1 ; point to next value
dec rmp ; End of Table reached
brne loop1
ldi ZH,HIGH(2*SineTable) ; Point Z to Table in flash
ldi ZL,LOW(2*SineTable)
rjmp loop2
;
; End of source code
;
; Include sinewave table
;
.INCLUDE "sine8_25.txt"
;
; End of program
;

http://www.avr-asm-tutorial.net/avr_en/source/SINEWAVE.asm1/20/2009 8:01:06 PM
http://www.avr-asm-tutorial.net/avr_en/source/MUSIC.asm

; ******************************************************************
; * Music on an STK200, using a R/2R network for playing tunes *
; * PortD has eight keys (active low), PortB generates the *
; * output for the R/2R-network, plays notes when key is activated *
; * ATMEL AT90S8515 at 4 Mcs/s *
; * (C)2005 by info@avr-asm-tutorial.net *
; ******************************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Constants
;
.EQU clock = 4000000 ; processor clock
.EQU cNSine = 32 ; Table length of sine wave
;
.DEF rLen = R1 ; length of delay for the sine wave
.DEF rCnt = R2 ; Counter for length delay
.DEF rmp = R16 ; multi purpose register
.DEF rTab = R17 ; counter for table length
;
ldi rmp,0xFF ; all bits of port B = output => R/2R network
out DDRB,rmp ; set data direction register
wtloop:
in rmp,PIND ; read the keys
cpi rmp,0xFF ; all keys inactive?
breq wtloop ; yes, wait until active
ldi ZH,HIGH(2*MusicTable) ; Point Z to music table
ldi ZL,LOW(2*MusicTable)
tabloop:
rol rmp ; rotate next lowest bit into carry
brcc tabfound ; found that key pressed
adiw ZL,1 ; point Z to next table value
rjmp tabloop ; check next bit
tabfound:
lpm ; read music table value to R0
mov rlen,R0 ; copy to delay, R0 used otherwise
;
; Play a tone until all keys are inactive
;
startsine:
ldi ZH,HIGH(2*SineTable) ; Set Z to sine wave table
ldi ZL,LOW(2*SineTable)
ldi rTab,cNSine ; Length of SineWave table
;
; The following code is optimized for reaching equal runtimes
; for all loop runs, clocks cycles needed are calculated
; for all instructions after their execution,
; clock cycles during table read / clock cycles at table end
;
loopsine:
in rmp,PIND ; 1/- Check if input still active
cpi rmp,0xFF ; 2/-
breq wtloop ; 3/- key not active any more, restart
nop ; 4/- delay to synchronize
loopnext:
lpm ; 7/3 read sinewave value to R0
out PORTB,R0 ; 8/4 copy to R/2R network
mov rCnt,rLen ; 9/5 Set delay counter value
; delay loop, requires 3*rLen-1 clock cycles
loopdelay:
dec rCnt ; (1) next counter value
brne loopdelay ; (2/1) not yet zero
; 3*rLen+8/3*rLen+4 at end of delay loop
adiw ZL,1 ; 3*rLen+10/3*rLen+6 next value in table
dec rTab ; 3*rLen+11/3*rLen+7 table counter
brne loopsine ; 3*rLen+13/3*rLen+8 play next value in table
ldi ZH,HIGH(2*SineTable) ; -/3*rLen+9 reload first table value
ldi ZL,LOW(2*SineTable) ; -/3*rLen+10
ldi rTab,cNSine ; -/3*rLen+11 Length of sine wave table
rjmp loopnext ; -/3*rLen+13 restart loop
;
; Table for delays to generate the 8 different frequencies
;
; frequency = clock / TableLength / ( 3 * rLen + 13 )
; rLen = ( clock /TableLength / frequency - 13 ) / 3
;
MusicTable:
; f=261.6 293.7 329.6 349.2 392.0 440.0 493.9 523.2 (should be)
.DB 155, 138, 122, 115, 102, 90, 80, 75
; f=261.5 292.7 329.8 349.2 391.9 441.7 494.1 525.2 (is really)
; differences caused by rounding and limited resolution)
;
; Sinewave table for 8 bit D/A
; Table length = 32 values
; VCC=5.000V, uLow=0.000V, uHigh=2.500V
; (generated by sinewave.pas)
;
Sinetable:
.DB 64,76,88,99,109,117,123,126
.DB 128,126,123,117,109,99,88,76
.DB 64,51,39,28,19,11,5,1
.DB 0,1,5,11,19,28,39,51
;
; End of program
;

http://www.avr-asm-tutorial.net/avr_en/source/MUSIC.asm1/20/2009 8:01:07 PM
AVR-Hardware-Testroutines

Path: Home => AVR-Overview => Software

Tutorial for learning the assembly


language of
AVR-Single-Chip-Processor AT90Sxxxx
of ATMEL applying practical examples.
Special software-know-how

(Click the links on the *.asm-files together with the shift key, if you want to download them.)
HTML- ASM-
Comment
Format Format
Reads the switches of the STK board, recodes the key into the number of LEDs
and displays them (key 0: all eight LEDs are on). A rather useless program but it
LPM LPM
demonstrates the use of the LPM command and the ROLling and JuMPing in
assembly language.
Jumps over the stack. Subroutine call not via the regular RCALL command but
by putting the jump adress on the stack. First the return adress has to be put on
JUMP JUMP
the stack, then the adress of the called subroutine. The jump and the return are
done via the RET command. Out of the series "tricky assembly programming"!
Macro examples. Just a useless program to demonstrate the use of macros in
MAC1 MAC1
assembler.
Macro examples. Demonstrates the use of jump to labels within and outside
MAC2 MAC2
macros.
MAC3 MAC3 Macro examples. Demonstrates the use of parameters in macros.

Back to the AVR-index

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/AVR_SOFT.html1/20/2009 8:01:09 PM
AVR-Software-Knowhow: <A HREF="beginner/REGISTER.html#LPM">LPM</A>-Command

Path: Home => AVR-Übersicht => Software => LPM-Befehl ;

Uses the LPM-command for reading bytes from


a table
; located in the code segment
;
; Reads the keys on the STK200 board and translates
; the position of the key to the number of LEDs by use
; of a table in the code segment and displays these
; LEDs (switch 0: 8 LEDs, switch 1: 1 LED, switch 2:
; 2 LEDs, etc.).
; A rather useless program, but it demonstrates the use
; of the LPM command to access the code segment and
; some ROLling and JUMPing.
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;

; Registers
;
.DEF erg=R0 ; The LPM-command uses R0
.DEF mpr=R16 ; Multi-funktion-register
;
; Registers ZL (R30) and ZH (R31) are also used but are already
; defined in 8515def.inc, so we don't need to do it here.
;

; Reset-/Interrupt-Vector

;
RJMP main
;
main: CLR mpr ; Load 0 to register mpr
OUT DDRD,mpr ; all D-Ports are Input switches
DEC mpr ; Load FF to Register B
OUT DDRB,mpr ; All B-Ports are outputs to LEDs
OUT PORTD,mpr ; All Pullups Port D on

loop: LDI ZL,LOW(liste2) ; Register pair Z points to


LDI ZH,HIGH(liste2) ; first Byte (FF) in the list
IN mpr,PIND ; Read switches
CPI mpr,0xFF ; All switches off? All LEDs off!
BREQ ;read
incp: INC ZL ;Point LSB to next byte on list
BRNE rolle ;overflow to MSB?
INC ZH ;MSB overflow, increment
rolle: ROR mpr ;shift Bit 0 to carry
BRLO incp ; Carry=1, switch is off, next list element
lesen: LPM ; Read byte on which Z points to, to R0
OUT PORTB,erg ; Output to LEDs
RJMP loop ; Loop
;
; The list with the LED combinations, each byte refers to a switch
; The values must be defined word-wise to avoid addition of a zero Byte.
; Use of .DB xx always adds a zero Byte. To define a word, you can also use ; .DB xx,yy, which are
linked to a word. The same applies to text input
; using .DB "abcd...". Even number of bytes or characters are linked, odd
; numbers receive a zero byte at the end of the list.
;
liste:
.DW 0xFEFF ; 1 LED, 0 LED (0 ist second, 1 first!)
.DW 0xF8FC ; 3 LEDs, 2 LEDs
.DW 0xE0F0 ; 5 LEDs, 4 LEDs
.DW 0x80C0 ; 7 LEDs, 6 LEDs
;
.EQU liste2=liste*2 ; This is needed, because adresses
; of the list are wordwise, access is bytewise

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTLPM.html1/20/2009 8:01:11 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTLPM.asm

; Uses the LPM-command for reading bytes from a table


; located in the code segment
;
; Reads the keys on the STK200 board and translates
; the position of the key to the number of LEDs by use
; of a table in the code segment and displays these
; LEDs (switch 0: 8 LEDs, switch 1: 1 LED, switch 2:
; 2 LEDs, etc.).
; A rather useless program, but it demonstrates the use
; of the LPM command to access the code segment and
; some ROLling and JUMPing.
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers
;
.DEF erg=R0 ; The LPM-command requires R0
.DEF mpr=R16 ; Multi-funktion register
;
; Uses the registers ZL (R30) and ZH (R31)! These are defined
; in 8515def.inc, so we don't need the definition here.
;
; Reset-/Interrupt-Vector
;
rjmp main
;
main:
clr mpr ; Load 0 to Register mpr
out DDRD,mpr ; all D-Ports are input for the switches
dec mpr ; Load FF to Register B
out DDRB,mpr ; All B-Ports are outputs to the LEDs
out PORTD,mpr ; All Pullups on D on
loop:
ldi ZL,LOW(liste2) ; Register pair Z points to the
ldi ZH,HIGH(liste2) ; first byte (FF) in the list
in mpr,PIND ; read switches
cpi mpr,0xFF ; All switches off? All LEDs off!
breq lesen ; Jump to lesen if all switches are off
incp:
inc ZL ; Point Z to next byte in the list
brne rolle ; No rollover to next MSB
inc ZH ; LSB rollover, increment MSB
rolle:
ror mpr ; Shift Bit 0 in Carry-Flag
brlo incp ; Carry=1, switch not pressed, next in list
lesen:
lpm ; Read the byte in the list, that register Z points to, to R0=erg
out PORTB,erg ; Transfer byte to the LEDs
rjmp loop ; Move in circles
;
; The list in the code segment, every byte represent a switch
; The values have to be defined as words! Otherwise a byte, inserted
; with the .DB xx directive, is always paired by the assembler with a
; zero byte and stored as word in the list. When using .DB xx,yy no
; extra zero byte is inserted. The same applies to text strings
; (.DB "abcd..."). Even numbers of bytes or characters are ok,
; odd numbers will be added a zero byte.
; When adding a word like 1234h to the list, the first byte in the list that
; is received from the LPM command is the LSB (34h), not the MSB (12h)!
;
liste:
.DW 0xFEFF ; 1 LED, 0 LEDs (0 ist second, 1 is first!)
.DW 0xF8FC ; 3 LEDs, 2 LEDs
.DW 0xE0F0 ; 5 LEDs, 4 LEDs
.DW 0x80C0 ; 7 LEDs, 6 LEDs
;
.EQU liste2=liste*2 ; This is needed because the adress is
; organized word-wise, while the read-
; operation is byte-wise.
;

http://www.avr-asm-tutorial.net/avr_en/source/TESTLPM.asm1/20/2009 8:01:13 PM
AVR-Hardware-Tutorial, RAM-JUMP

Path: Home => AVR-Overview => Software => JUMP-command

; Calls a subroutine via the stack

;
; This subroutine call is not implemented via the RCALL command
; but by using the processor stack. The sequence is: first the
; return adress is pushed onto the stack, then the adress of
; the subroutine to be called. The jump to the subroutine and
; back to the main program is done by executing the RET-
; command (popping the adress from the stack and jump to
; this adress).
; This adressing mode is a very unusual opportunity, e.g. to write
; multiple jump adresses to a table and calculate the target adress.
; It is not meant for the beginner.
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
.DEF mpr=R16 ; As always, a multi purpose working register
;

; Reset-/Interrupt-Vector table

;
RJMP main
;
main: LDI mpr,HIGH(RAMEND) ; Stack init
OUT SPH,mpr
LDI mpr,LOW(RAMEND)
OUT SPL,mpr

LDI mpr,LOW(retret) ; Push return adress to the stack


PUSH mpr
LDI mpr,HIGH(retret)
PUSH mpr

LDI mpr,LOW(testup) ; Push subroutine adress to the stack


PUSH mpr
LDI mpr,HIGH(testup)
PUSH mpr

RET ; Jump to the subroutine!


;

; The called subroutine swiches all LEDs on

;
retret: LDI mpr,0x00 ; If successful, switch all LEDs on
OUT PORTB,mpr
loop: RJMP loop ; Halt
;
;

; Test program to be called


;
testup: LDI mpr,0xFF ; All LED drivers on
OUT DDRB,mpr
RET ; Return to adress on the stack

Back to the software-page

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTJMP.html1/20/2009 8:01:14 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTJMP.asm

; Tests subroutine calls via stack


;
; This subroutine call is not implemented via the RCALL command
; but by using the processor stack. The sequence is: first the
; return adress is pushed onto the stack, then the adress of
; the subroutine to be called. The jump to the subroutine and
; back to the main program is done by executing the RET-
; command (popping the adress from the stack and jump to
; this adress).
; This adressing mode is a very unusual opportunity, e.g. to write
; multiple jump adresses to a table and calculate the target adress.
; It is not meant for the beginner.
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
.DEF mpr=R16 ; As always, a multi-purpose working register
;
; Reset-/Interrupt-Vector table
;
rjmp main
;
main:
ldi mpr,HIGH(RAMEND) ; Stack setup
out SPH,mpr
ldi mpr,LOW(RAMEND)
out SPL,mpr
ldi mpr,LOW(retret) ; Push return adress onto stack
push mpr
ldi mpr,HIGH(retret)
push mpr
ldi mpr,LOW(testup) ; Push subroutine adress onto stack
push mpr
ldi mpr,HIGH(testup)
push mpr
ret ; Jump to subroutine
;
; The return routine switches all lamps on to signal correct execution
;
retret:
ldi mpr,0x00 ; Switch all LEDs on, if correct
out PORTB,mpr
loop:
rjmp loop ; stop execution
;
;
; Test subroutine to be jumped to
;
testup:
ldi mpr,0xFF ; All lamp drivers tov output
out DDRB,mpr
ret ; Jump back to call adress on the stack

http://www.avr-asm-tutorial.net/avr_en/source/TESTJMP.asm1/20/2009 8:01:16 PM
Testprogram to demonstrate Macros, Example 1

Path: Home => AVR-Overview => Software => Macro example 1


; *****************************************************
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro, a piece of code that
; will be inserted into your program whenever you
; need it there. Whenever you need the same sequences
; all over again and you don't want to call a subroutine
; you should write a macro and insert this sequence by
; calling that macro.
;
.MACRO TestMacro
Inc mpr
Inc mpr
Inc mpr
.ENDMACRO
;
;
; Start of main program
;
LDI mpr,0xFF ; Set PortB (LEDs) to be output
OUT DDRB,mpr ; to Data Direction Register
CLR mpr ; Clear the register
TestMacro ; Insert the macro here (three INCs)
TestMacro ; Insert it once again here (another 3)
COM mpr ; Invert the result to display it
OUT PORTB,mpr ; and write it to the LEDs
loop: RJMP loop ; and end the program in a loop
;
; Assembling this code should result in a 11 word long
; binary, because the two TestMacro-macros blow up to
; six INCs during the assembly process.
;
; After execution the LEDs PB.1 and PB.2 should be on,
; all others should be off to display the result (6 dec
; = 0000.0110 binary)!
;

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTMAC1.html1/20/2009 8:01:18 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC1.asm

; *****************************************************
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro, a piece of code that
; will be inserted into your program whenever you
; need it there. Whenever you need the same sequences
; all over again and you don't want to call a subroutine
; you should write a macro and insert this sequence by
; calling that macro.
;
.MACRO TestMacro
inc mpr
inc mpr
inc mpr
.ENDMACRO
;
;
; Start of main program
;
ldi mpr,0xFF ; Set PortB (LEDs) to be output
out DDRB,mpr ; to Data Direction Register
clr mpr ; Clear the register
testmacro ; Insert the macro here (three INCs)
testmacro ; Insert it once again here (another 3)
com mpr ; Invert the result to display it
out PORTB,mpr ; and write it to the LEDs
loop:
rjmp loop ; and end the program in a loop
;
; Assembling this code should result in a 11 word long
; binary, because the two TestMacro-macros blow up to
; six INCs during the assembly process.
;
; After execution the LEDs PB.1 and PB.2 should be on,
; all others should be off to display the result (6 dec
; = 0000.0110 binary)!
;

http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC1.asm1/20/2009 8:01:19 PM
Testprogram to demonstrate Macros, Example 2

Path: Home => AVR-Overview => Software => Macro example 2


; *****************************************************
; * Jump labels within a macro: the answer is "yes" *
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro which includes a label
; within that macro (mjmp) and a jump to a label
; outside that macro. Both jumps are translated
; correctly.
;
.MACRO TestMacro
Inc mpr ; INC the register mpr
BRNE mjmp ; If no overflow skip the next
RJMP ovf ; Jump if overflow occurs
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Start of main program
;
LDI mpr,0xFF ; Set PortB (LEDs) to be output
OUT DDRB,mpr ; to Data Direction Register
;
LDI mpr,0xFE ; Set the register to 254
TestMacro ; Insert the macro here (one INC)
TestMacro ; Insert it once again here (another INC)
; As there should have been an overflow during the last INC
; the following code should not be reached. If executed,
; it would result in all LEDs on.
;
outp: OUT PORTB,mpr
loop: RJMP loop ; and end the program in a loop
;
; The overflow should occur and this code will be executed
;
ovf: LDI mpr,0xFF ; Blank all LEDs
OUT PORTB,mpr ; at Port B
RJMP loop ; Jump to indefinite loop
;
; After execution all the LEDs PB.0 to PB.7 should be off.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTMAC2.html1/20/2009 8:01:21 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC2.asm

; *****************************************************
; * Jump labels within a macro: the answer is "yes" *
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro which includes a label
; within that macro (mjmp) and a jump to a label
; outside that macro. Both jumps are translated
; correctly.
;
.MACRO TestMacro
inc mpr ; INC the register mpr
brne mjmp ; If no overflow skip the next
rjmp ovf ; Jump if overflow occurs
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Start of main program
;
ldi mpr,0xFF ; Set PortB (LEDs) to be output
out DDRB,mpr ; to Data Direction Register
;
ldi mpr,0xFE ; Set the register to 254
testmacro ; Insert the macro here (one INC)
testmacro ; Insert it once again here (another INC)
; As there should have been an overflow during the last INC
; the following code should not be reached. If executed,
; it would result in all LEDs on.
;
outp:
out PORTB,mpr
loop:
rjmp loop ; and end the program in a loop
;
; The overflow should occur and this code will be executed
;
ovf:
ldi mpr,0xFF ; Blank all LEDs
out PORTB,mpr ; at Port B
rjmp loop ; Jump to indefinite loop
;
; After execution all the LEDs PB.0 to PB.7 should be off.

http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC2.asm1/20/2009 8:01:22 PM
Testprogram to demonstrate Macros, Example 3

Path: Home => AVR-Overview => Software => Macro example 3


; *****************************************************
; * To pass a parameter to a macro is easy to program *
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info!at!avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro which includes a label
; within that macro (mjmp) and a jump to a label
; outside that macro. Both jumps are translated
; correctly.
;
.MACRO TestMacro
LDI mpr,@0 ; Set mpr-value to first parameter
Inc mpr ; Add one
BRNE mjmp ; If no overflow skip the next
RJMP ovf ; Jump if overflow occurs
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Start of main program
;
LDI mpr,0xFF ; Set PortB (LEDs) to be output
OUT DDRB,mpr ; to Data Direction Register
;
LDI mpr,0xFE ; Set the register to 254
; Here comes the macro: 0xFF is passed to it, then INCed
; and, as it is zero, jumps to the label ovf
;
TestMacro(0xFF) ; Insert the macro here
;
; As there should have been an overflow during the last INC
; the following code should not be reached. If executed,
; it would result in all LEDs on.
;
outp: OUT PORTB,mpr
loop: RJMP loop ; and end the program in a loop
;
; The overflow should occur and this code will be executed
;
ovf: LDI mpr,0xFF ; Blank all LEDs
OUT PORTB,mpr ; at Port B
RJMP loop ; Jump to indefinite loop
;
; After execution all the LEDs PB.0 to PB.7 should be off.

©2002 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/TESTMAC3.html1/20/2009 8:01:24 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC3.asm

; *****************************************************
; * To pass a parameter to a macro is easy to program *
; * Demonstrates the use of macros with the ATMEL *
; * assembler, just a test program for use with the *
; * ATMEL STK200 board, (C) 2000 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; *****************************************************
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Used registers
;
.DEF mpr=R16 ; a multi purpose register
;
; The following is the macro which includes a label
; within that macro (mjmp) and the value for the
; register is handed over with the first parameter
; referenced by @0.
;
.MACRO TestMacro
ldi mpr,@0 ; Set mpr-value to first parameter
inc mpr ; Add one
brne mjmp ; If no overflow skip the next
rjmp ovf ; Jump if overflow occurs
mjmp:
.ENDMACRO
;
.LISTMAC
;
; Start of main program
;
ldi mpr,0xFF ; Set PortB (LEDs) to be output
out DDRB,mpr ; to Data Direction Register
;
ldi mpr,0xFE ; Set the register to 254
; Here comes the macro: 0xFF is passed to it, then INCed
; and, as it is zero, jumps to the label ovf
;
testmacro(0xff) ; Insert the macro here
;
; As there should have been an overflow during the last INC
; the following code should not be reached. If executed,
; it would result in all LEDs on.
;
outp:
out PORTB,mpr
loop:
rjmp loop ; and end the program in a loop
;
; The overflow should occur and this code will be executed
;
ovf:
ldi mpr,0xFF ; Blank all LEDs
out PORTB,mpr ; at Port B
rjmp loop ; Jump to indefinite loop
;
; After execution all the LEDs PB.0 to PB.7 should be off.

http://www.avr-asm-tutorial.net/avr_en/source/TESTMAC3.asm1/20/2009 8:01:26 PM
Connecting a keypad to an AVR

Pfad: Home => AVR-Overview => keypad

Connecting a keypad to an AVR


This page shows how to connect a common 12-key-keypad to an AVR and read it by assembler
software. The chapters are:

1. How a keypad works


2. AVR: I/O-connection of the matrix
3. AVR: Connecting to an ADC with a resistor network

1. How a keypad works


Keypads are switches, that are connected to rows and columns.
If key "1" is pressed, the column 1 is electrically connected to
row 1, if key "2" is pressed column 2 with row 1, and so on ...

To find out, if any one of the 12 keys is pressed, it


would only be necessary to tie the three column lines to
ground, connect all four row lines and, via a resistor of
10 kΩ, pull them to the operating voltage. If no key is
pressed, the row lines are at plus. Any pressed key pulls
down the row lines to zero volts.

To detect, which one of the 12 keys is pressed, pull down the three column lines one by one to
ground (the other two column lines to plus) and read the resulting four row-lines. If one of the four
row-lines is low, stop further reading and identify the key code from the column and row info. Like
that:
Column Row Key
Col1 Col2 Col3 Row1 Row2 Row3 Row4 Character Binary code
0 0 0 1 1 1 1 (none) 1111
0 1 1 0 1 1 1 1 0001
1 0 1 0 1 1 1 2 0010
1 1 0 0 1 1 1 3 0011
0 1 1 1 0 1 1 4 0100
1 0 1 1 0 1 1 5 0101
1 1 0 1 0 1 1 6 0110
0 1 1 1 1 0 1 7 0111
1 0 1 1 1 0 1 8 1000
1 1 0 1 1 0 1 9 1001
0 1 1 1 1 1 0 * 1010
1 0 1 1 1 1 0 0 0000
1 1 0 1 1 1 0 # 1011

Reading such a keypad using digital logic components, you need at least:

● an oscillator, a shift register and a start/stop gate for generating the column signals,
● detection if one of the four row signals is zero,
● a recoder for conversion of the seven signals to the keycode.

Or a complete IC doing all that (probably you won't get such an IC at your local electronic parts
dealer). Or you better use a micro.

To top of page

2. AVR: I/O-connection of the matrix


A keypad matrix can be connected directly to an I/O port of an
AVR, with no additional components.
The example shows a connection to the lower seven I/O pins of
Port B. Other ports can be used similiarly.
The port pins PB4..PB6 are defined as outputs, they provide the
column signals. The port pins PB0..PB3 are used to read in the
row results. Pull-up resistors on these inputs are enabled by
software, external resistors are not necessary.

The following software example first demonstrates initialization


of the ports. This software part has to be excecuted only once at
the AVR's program start.

Init-routine

;
; Init keypad-I/O
;
.DEF rmp = R16 ; define a multipurpose register
; define ports
.EQU pKeyOut = PORTB ; Output and Pull-Up-Port
.EQU pKeyInp = PINB ; read keypad input
.EQU pKeyDdr = DDRB ; data direction register of the port
; Init-routine
InitKey:
ldi rmp,0b01110000 ; data direction register column lines
output
out pKeyDdr,rmp ; set direction register
ldi rmp,0b00001111 ; Pull-Up-Resistors to lower four port
pins
out pKeyOut,rmp ; to output port

Check for any key pressed

The following routine detects if any one of the 12 keys is pressed. This routine is called in intervals, e.
g. in a delay loop or by use of a timer.

;
; Check any key pressed
;
AnyKey:
ldi rmp,0b00001111 ; PB4..PB6=Null, pull-Up-resistors to
input lines
out pKeyOut,rmp ; of port pins PB0..PB3
in rmp,pKeyInp ; read key results
ori rmp,0b11110000 ; mask all upper bits with a one
cpi rmp,0b11111111 ; all bits = One?
breq NoKey ; yes, no key is pressed

Identify the key pressed

Now the keypad is read out. One after the other the port bits PB6, PB5 and PB4 are set to low, and
PB0..PB3 are checked for zeros. The register pair Z (ZH:ZL) points to a table with the key codes.
When leaving the routine, this pair points to the key code of the pressed key. By using the LPM
instruction, the key code is read from the table in the flash memory to the register R0.

;
; Identify the key pressed
;
ReadKey:
ldi ZH,HIGH(2*KeyTable) ; Z is pointer to key code table
ldi ZL,LOW(2*KeyTable)
; read column 1
ldi rmp,0b00111111 ; PB6 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; read input line
ori rmp,0b11110000 ; mask upper bits
cpi rmp,0b11111111 ; a key in this column pressed?
brne KeyRowFound ; key found
adiw ZL,4 ; column not found, point Z one row down
; read column 2
ldi rmp,0b01011111 ; PB5 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; read again input line
ori rmp,0b11110000 ; mask upper bits
cpi rmp,0b11111111 ; a key in this column?
brne KeyRowFound ; column found
adiw ZL,4 ; column not found, another four keys down
; read column 3
ldi rmp,0b01101111 ; PB4 = 0
out pKeyOut,rmp
in rmp,pKeyInp ; read last line
ori rmp,0b11110000 ; mask upper bits
cpi rmp,0b11111111 ; a key in this column?
breq NoKey ; unexpected: no key in this column pressed
KeyRowFound: ; column identified, now identify row
lsr rmp ; shift a logic 0 in left, bit 0 to carry
brcc KeyFound ; a zero rolled out, key is found
adiw ZL,1 ; point to next key code of that column
rjmp KeyRowFound ; repeat shift
KeyFound: ; pressed key is found
lpm ; read key code to R0
rjmp KeyProc ; countinue key processing
NoKey:
rjmp NoKeyPressed ; no key pressed
;
; Table for code conversion
;
KeyTable:
.DB 0x0A,0x07,0x04,0x01 ; First column, keys *, 7, 4 und 1
.DB 0x00,0x08,0x05,0x02 ; second column, keys 0, 8, 5 und 2
.DB 0x0B,0x09,0x06,0x03 ; third column, keys #, 9, 6 und 3

Debouncing

The routines KeyProc and NoKeyPressed have to debounce the pressed key. For example by
counting a counter up whenever the same key is identified. Repeat this for e.g. 50 milliseconds. The
NoKeyPressed routine clears the counter and the key pressed. Because the timing depends on other
necessary timing requirements of the AVR program, it is not shown here.

Hints, Disadvantages

The routines shown above do not leave more time between the setting of the column address and the
reading of the row information. At high clock frequencies and/or longer connections between keypad
and processor it is necessary to leave more time between write and read (e.g. by inserting NOP
instructions).
The internal pull-ups resistors have values around 50 kΩ. Long lines or a noisy environment might
interfere and produce glitches. If you like it less sensitive, add four external pull-ups.

A disadvantage of the circuit is that it requires seven port lines exclusively. The modification with an
AD converter and a resistor network (see chapter 3) is more economic and saves port lines.

To the top of that page

3. Connection to an ADC with a resistor matrix

Most of the Tiny and Mega-AVR devices nowadays have an


AD converter on board. Without additional external hardware
these are capable of measuring analog voltages and resolve
these with 10 bit resolution. Those who want to save I/O ports
only have to get the keypad to produce an analog voltage.
That's the task for a resistor matrix.

Resistor matrix

This is such a resistor


matrix. The columns are
connected to ground, in
between the column
connections are three
stacked resistors. The rows
are connected via four such
stacked resistors to the
operating voltage (e.g. 5 V).
The AD converter input is
blocked by a condensator
of 1 nF because the ADC
doesn't like high
frequencies, that could be
caught by the keys, the
resistors and the more or
less long lines in between
all this.
If the key "5" is pressed, a voltage divider gets active:

* 1 k + 820 Ω = 1,82k to ground,


* 3,3 k + 680 Ω + 180 Ω = 4,16k to plus.

At an operating voltage of 5 Volt a divided voltage of

5 * 1,82 / (1,82 + 4,16) = 1,522 Volt

is seen on the AD converter input. If we consider 5%


tolerance of the resistors, the resulting voltage is somewhere
between 1,468 and 1,627 Volts. The 10-bit AD converter
converts this (at 5 V reference voltage) to a value between
300 and 333. If we ignore the lower two bits of the result (e.g.
divide the AD result by four or left-adjusting the result - if the
ADC provides that function) this yields an 8-bit-value
between 74 and 78.
Each key pressed produces a typical voltage range, to be
converted to the key code.
Voltages and key recognition

The combinations of resistors yield the voltages assembled


in the following table. Given are the voltage ranges of the
keys, the 8-bit-AD converter values for these keys and the
optimal detection values between the different keys.

Voltage 8-bit-AD value Detection


Key
V(min.) V(typ.) V(max.) min. typ. max. (from AD value)
1 0,225 0,248 0,272 11 13 14 7
2 0,396 0,434 0,474 20 22 25 18
3 0,588 0,641 0,698 29 33 36 28
4 0,930 0,969 1,048 47 49 54 42
5 1,468 1,522 1,627 74 78 84 64
6 1,959 2,020 2,139 99 103 110 91
7 2,563 2,688 2,809 130 137 144 121
8 3,285 3,396 3,500 167 173 180 156
9 3,740 3,832 3,917 190 195 201 185
* 4,170 4,237 4,298 212 216 221 207
0 4,507 4,550 4,588 229 232 235 225
# 4,671 4,700 4,726 238 240 242 237

As can be seen from the table, there is no overlapping of the different detection values for the keys,
taking 5% tolerance of the resistors into account.

Those who like to play around with other resistor combinations, can download the calculation sheet
(as Open-Office-Format, as Excel-XP-Format).

Hints for the AD converter hardware

ATtiny devices in the most cases provide only the opportunity to use an internally generated voltage
or the supply voltage of the AVR as reference for the AD converter. For the keypad conversion only
the supply voltage is suitable as reference. This option has to be selected when initiating the AD
converter hardware at program start.

Many ATmega types can connect the reference voltage to an external pin, AREF. This pin can either
be input or output. It is an output if either the supply voltage or the internal reference are selected as
AD converter reference. In this case the AREF pin should have a condensator to ground to further
reduce noise on the reference voltage. The AREF pin is an input, if an external reference source is
selected as option. In this case an external source provides the reference voltage. If an external source
provides the reference voltage, the keypad matrix should also be supplied by this source. Note in that
case that the keypad consumes up to 10 mA, to improve noise sensitivity.

ATmega devices allow to supply the AD converter from an extra pin (AVCC) to further reduce noise.
If only the keypad uses AD conversion the low necessary resolution of 8 bits does not require a
separate supply for the AVCC pin, it can be tied to the normal supply voltage. If other measuring
tasks have to be performed on other channels, the AVCC pin should be connected to the supply
voltage via a coil of 22 µH and should be blocked by a condensator of 100 nF to ground.

Initiation and reading the AD converter result

For reading the keypad matrix voltage one AD converter channel is required. The AD converter is
initiated once during program start. The two example codes show a start sequence for single
conversion, here for an ATmega8, and one for an interrupt driven automatic start of the ADC, here
for an ATtiny13.

ATmega8: manual start of the ADC

The first example shows a routine for an ATmega8, without interrupts, with a manual start and stop
of the the AD converter. The keypad signal is connected to AD channel ADC0.

.DEF rKey = R15 ; Register for AD value


.DEF rmp = R16 ; Multi purpose register
; set MUX to channel 0, left adjust the result, AREF taken
from AVCC
ldi rmp,(1<<REFS0)|(1<<ADLAR) ; ADMUX channel 0, AREF from
AVCC
out ADMUX,rmp
; switch AD conversion on, start conversion, divider rate =
128
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
; wait until the AD conversion is complete
WaitAdc1:
; check ADSC bit, conversion complete if bit is zero
sbic ADCSRA,ADSC ; conversion ready?
rjmp WaitAdc1 ; not yet
; read MSB of the AD conversion result
in rKey,ADCH
; switch AD converter off
ldi rmp,(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ; switch ADC off
out ADCSRA,rmp

Please note that this single conversion requires 25 * 128 clock cycles, at 1 Mcs/s clock 3.2 milli-
seconds. Only do this that way, running around in circles, if you don't need to care for other things in
between this time delay (except if these other things are done inside interrupts).

ATtiny13: Autostart AD conversion, interrupt-driven

Yes, an ATtiny13 with its 8 pins can read our keypad matrix (we cannot connect the keypad matrix
itself due to the limited number of I/O pins).

A typical routine for this task would be the following sequence, that converts the voltage on ADC3
(pin 2 of the ATtiny13) continously (after conversion complete, the next conversion is started
automatically).

;
; Start AD converter
;
; PB3=ADC3 is used for the conversion
ldi rmp,0b00001000 ; disconnect the PB3 digital driver,
saves supply current
out DIDR0,rmp
; Reference = supply voltage, Left-adjust the result
; ADMUX to ADC3
ldi rmp,0b00100011 ; reference voltage = supply voltage,
chose ADC3
out ADMUX,rmp
; select autostart option
ldi rmp,0b00000000 ; free-running conversion (autostart)
out ADCSRB,rmp
; start ADC, allow interrupt, select clock divider
ldi rmp,0b11101111 ; start ADC, autostart,
out ADCSRA,rmp ; Int Enable, clock divider to 128
; initiation complete

Running in interrupt mode requires defining the respective int jump vector, e.g.

;
; Reset and int vectors, ATtiny13
;
.CSEG ; assemble into code segment
.ORG $0000 ; at the beginning of the code segment
rjmp main ; Reset vector
reti ; Int0 interrupt vector
reti ; PCINT0 vector
reti ; TC0 overflow vector
reti ; Eeprom ready vector
reti ; Analog comparator int vector
reti ; TC0 CompA vector
reti ; TC0 CompB vector
reti ; WDT vector
rjmp intadc ; ADC conversion complete vector
;

Of course, the stack must be initiated to use interrupts, and the interrupt status flag must be set (SEI).

The service routine intadc reads the AD conversion result. Because Left-Adjust has been selected, it
is sufficient to read the MSB of the result:

;
; Interrupt Service Routine AD conversion
;
.DEF rKey = R15 ; result register for the conversion result
intadc:
in rKey,ADCH ; read AD converter MSB
reti ; return from interrupt
;

The register rKey continously provides the current value of the resistor matrix.

Converting the AD result to the key code

The conversion result is, as such, not very useful. The voltages and the conversion result do not
follow easy mathematical laws (the resistor values 4.7 - 5.6 - 6.8 - 8.2 must have been designed by a
drunken math professor, the formula V = R1 / (R1 + R2) is not very easy to handle), so that we better
use a table to resolve our key codes. The table cannot be a primitive look-up table, because we have
256 different possible results of the conversion, and we like more slim tables.

Like a monkey, we climb the matrix tree by going step by step through the following table:

KeyTable:
.DB 7, 255, 18, 1, 28, 2, 42, 3, 64, 4, 91, 5
.DB 121, 6, 156, 7, 185, 8, 207, 9, 225, 10, 237, 0, 255, 11

The first byte is the compare value for our conversion result, the second byte is the key code, if this
compare value is greater than our result. If the result is between 0 and <7: no key is pressed (key code
is 255), if it is between 7 and <18 the key code is 1, etc.

Or, if you prefer ASCII for the key codes:

KeyTable:
.DB 7, 0 , 18, '1', 28, '2', 42, '3', 64, '4', 91, '5'
.DB 121, '6', 156, '7', 185, '8', 207, '9', 225, '*', 237, '0',
255, '#'

The code for key translation goes like this:

;
; Converting a AD result to a key code
;
GetKeyCode:
; if the AD result can change in between, the result must
be copied first
mov R1,rKey ; copy AD result to R1
ldi ZH,HIGH(2*KeyTable) ; Z points to conversion table
ldi ZL,LOW(2*KeyTable)
GetKeyCode1:
lpm ; read one table value
cp R1,R0 ; compare AD result with table value
brcs GetKeyCode2 ; less than table value, key identified
inc R0 ; test, if table end is reached
breq GetKeyCode2 ; reached end of table
adiw ZL,2 ; point to next table entry
rjmp GetKeyCode1 ; go on comparing next entry
GetKeyCode2:
adiw ZL,1 ; point to MSB = key code
lpm ; read key code to R0
;

Of course we have to check, if no key is pressed (R0 = 0xFF resp. if ASCII: R0 = 0) and we have to
check for glitches (if the same key code comes 20 or more times, I take it for serious ...).

Experiences

The hard- and software work very reliable. In the first version the resistor values of the matrix were
ten times higher. This version was more vulnerable to HF noise, e.g. when transmitting with a 2 W
VHF transmitter nearby.

To the top of the page

©2006-2009 by http://www.avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/avr_en/keypad/keyboard.html1/20/2009 8:01:32 PM
Assembler sources for the AVR-Tutorial

Path: Home => AVR-Overview => source files

Links to all source files of this tutorial


● 8515std.asm
● ADC8.asm 8-Bit-AD-converter
● avr_pwm1.pas, Pascal Simulator for selecting R and C for ADC PWMs
● CLOCK.asm
● DIV8E.asm
● eggtimer.asm
● FP_CONV10_EN.asm
● FP_CONV8_EN.asm
● LCD_INC.asm
● LCD_TEST.asm
● Lcd4IncE.asm
● Lcd4IncCE.asm
● MULT8E.asm
● PCM2PWG4.asm
● PWGSIO2.asm
● R/2R: sawtooth1
● R/2R: sawtooth2
● R/2R: triangle
● R/2R: sinewave
● R/2R: wavetable
● R/2R: music
● SIOHEX.asm
● Steppermotor
● TEST1.asm
● TEST2.asm
● TEST3.asm
● TEST4.asm
● TESTEEP.asm
● TESTJMP.asm
● TESTKBD.asm
● TESTLCD.asm
● TESTLPM.asm
● TESTMAC1.asm
● TESTMAC2.asm
● TESTMAC3.asm
● TESTRAM.asm
● TESTSIO.asm

http://www.avr-asm-tutorial.net/avr_en/source/index.html1/20/2009 8:01:39 PM
http://www.avr-asm-tutorial.net/avr_en/source/8515std.asm

; ***************************************************************
;* *

;* *

;* *

;* *

;* *

; * (C)2002 by Last change: *


; ***************************************************************
;
; Hardware requirements:
;
; Software features:
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Constants
;
.EQU xyz = 12345
;
; Used registers
;
.DEF mpr = R16
;
; Code starts here
;
.CSEG
.ORG $0000
;
; Reset- and Interrupt-vectors
;
rjmp Start ; Reset-vector
rjmp IInt0 ; External Interrupt Request 0
rjmp IInt1 ; External Interrupt Request 1
rjmp TCpt1 ; Timer/Counter1 Capture event
rjmp TCmpA ; Timer/Counter1 Compare match A
rjmp TCmpB ; Timer/Counter1 Compare Match B
rjmp TOvf1 ; Timer/Counter1 Overflow
rjmp TOvf0 ; Timer/Counter0 Overflow
rjmp SIStc ; SPI Serial Transfer Complete
rjmp URxAv ; Uart Rx char available
rjmp UTxDe ; Uart Tx data register empty
rjmp UTxCp ; Uart Tx complete
rjmp AnaCp ; Analog comparator
;
; ************** Interrupt service routines ********
;
; External Interrupt 0
;
IInt0:
reti
;
; External Interrupt 1
;
IInt1:
reti
;
; Timer/Counter 1, Capture event
;
TCpt1:
reti
;
; Timer/Counter 1, Compare match interrupt A
;
TCmpA:
reti
;
; Timer/Counter 1, Compare match interrupt B
;
TCmpB:
reti
;
; Timer/Counter 1, Overflow interrupt
;
TOvf1:
reti
;
; Timer/Counter 0, Overflow interrupt
;
TOvf0:
reti
;
; SPI Serial Transfer Complete interrupt
;
SIStc:
reti
;
; Uart Rx Complete Interrupt
;
URxAv:
reti
;
; Uart Data register empty interrupt
;
UTxDe:
reti
;
; Uart Tx complete interrupt
;
UTxCp:
reti
;
; Analog comparator interrupt
;
AnaCp:
reti
;
; **************** End of interrupt service routines ***********
;
; Various subroutines
;
; **************** End of the subroutine section ***************
;
; ******************** Main program ****************************
;
; Main program routine starts here
;
Start:
rjmp start

http://www.avr-asm-tutorial.net/avr_en/source/8515std.asm1/20/2009 8:01:40 PM
http://www.avr-asm-tutorial.net/avr_en/source/LCD_TEST.asm

; *****************************************************
; * Demonstrates the use of the Include routines *
; * LCD_INC.ASM for use with the LCD on board of the *
; * ATMEL STK200 (C) 1999 Gerhard Schmidt *
; * Report bugs to info@avr-asm-tutorial.net *
; *****************************************************
;
;
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
.def mpr=R16 ; My multipurpose register, required
; Reset-/Interrupt-Vectors
rjmp main
; Includes the LCD-routines, file must be in the same path
.INCLUDE "LCD_INC.ASM"
; Main program
main:
ldi mpr,LOW(RAMEND) ; Set up stack
out SPL,mpr
ldi mpr,HIGH(RAMEND)
out SPH,mpr
ldi mpr,0xC0 ; Switch on external SRAM and WAIT
out MCUCR,mpr
rcall lcd_cl ; Clears display
rcall lcd_st ; Standard display mode
ldi mpr,0x05; Cursor position to line 1, col 5
rcall lcd_sc
ldi mpr,'H' ; Output Hello World
rcall lcd_ch
ldi mpr,'e'
rcall lcd_ch
ldi mpr,'l'
rcall lcd_ch
rcall lcd_ch
ldi mpr,'o'
rcall lcd_ch
ldi mpr,0x45 ; Cursor position to line 2, col 5
rcall lcd_sc
ldi mpr,'W'
rcall lcd_ch
ldi mpr,'o'
rcall lcd_ch
ldi mpr,'r'
rcall lcd_ch
ldi mpr,'d'
rcall lcd_ch
ldi mpr,'!'
rcall lcd_ch
rcall lcd_on
loop:
rjmp loop ; Uff! Next week we learn how to create and read a table

http://www.avr-asm-tutorial.net/avr_en/source/LCD_TEST.asm1/20/2009 8:01:41 PM
http://www.avr-asm-tutorial.net/avr_en/source/TESTKBD.asm

; Test of a decimal keyboard


;
; Reads the keyboard on port B and displays the activated key on the LEDs
; in hex format.;
; The decimal keyboard is attached to port B:
; Bit 6: *=Bit0 7=Bit1 4=Bit2 1=Bit3
; Bit 5: 0=Bit0 8=Bit1 5=Bit2 2=Bit3
; Bit 4: #=Bit0 9=Bit1 6=Bit2 3=Bit3
;
; Tests with this program showed that parallel operation of the LEDs and
; of the keyboard on the same port (B) is practically impossible due to
; insufficient driving currents of the port pins. No correct values are read.
;
; 8515-Definitions
.NOLIST
.INCLUDE "C:\avrtools\appnotes\8515def.inc"
.LIST
;
; Registers used
.def mpko=R15 ; Last keyboard status
.def mpr=R16 ; Multi-function register
.def mpk=R25 ; Multi-function register for keyboard-interrupt
;
; RAM-Adresses
.equ taste=$0060 ; First Ram-adress, here the pressed key will be placed
;
; Reset-/Interrupt vector table, most of the inactive
rjmp main
reti ; Ext Int 0
reti ; Ext Int 1
reti ; TC1 Capture
rjmp test ; TC1 Compare A
reti ; Compare B
reti ; TC1 Overflow
reti ; TC0 Overflow
reti ; Serial Transfer Complete
reti ; Serial Rx Complete
reti ; Data Register Empty
reti ; Serial Tx Complete
reti ; Analog Comparator
; Main program
main:
ldi mpr,HIGH(RAMEND) ; Stack Pointer Init for Interrupts
out SPH,mpr
ldi mpr,LOW(RAMEND)
out SPL,mpr
; General control register
clr mpr ; no SRAM, no Wait, no Sleep-Mode,
out MCUCR,mpr ; Ext.Int not used
; Port B is output und keyboard-Input
ldi mpr,0x70 ; all as Output
out DDRB,mpr
ldi mpr,0x00 ; all lamps on
out PORTB,mpr
sts Taste,mpr
;
; Timer/Counter 0 init
ldi mpr,$00 ; Prescaler = 256
out TCCR0,mpr
; Timer 1 init
ldi mpr,0b00000000 ; Disable Timer Output and PWM-Mode
out TCCR1A,mpr ; in Timer Control Register 1A
ldi mpr,0b00001011 ; No input noise canceling, clear counter after
; match, Prescaler = 64 ==> 62500 Hz = 16 µs
out TCCR1B,mpr ; in Timer Control Register 1B
ldi mpr,HIGH(625) ; Compare-value in Compare-Register A
out OCR1AH,mpr ; High Byte first
ldi mpr,LOW(625)
out OCR1AL,mpr ; Low Byte last
ldi mpr,0xFF ; No Interrupt on Compare B
out OCR1BH,mpr ; High Byte first
out OCR1BL,mpr ; Low Byte last
; Interrupt start
clr mpr ; External interrupts disable
out GIMSK,mpr ; to General Interrupt mask register
ldi mpr,0b01000000 ; Timer 1: Overflow Int Off, Compare A Int on,
out TIMSK,mpr ; Compare B Int Off, Input Int Off, Timer 0: Int Off
sei ; interrupt enable
; Incefinite Loop, all execution is interrupt-driven
loop:
rjmp loop
; Interrupt Routine for TC1 Compare Match B
tc1ci:
in mpk,SREG ; save Status-Register
push mpk
ldi mpk,0b11110000 ; Upper Nibble to output, lower to input
out DDRB,mpk ; on Port B
ldi mpk,0x0F ; Upper Nibble to zero, lower nibble sets Pullup resistors
out PORTB,mpk
in mpk,PINB ; Read result from keyboard
cp mpk,mpko ; Compare with older value
breq tc1cir ; ne change: return
mov mpko,mpk ; Copy new status to old status
sts taste,mpk ; New LED-Status
tc1cir:
ldi mpk,0xFF ; Port B to all output
out DDRB,mpr
lds mpk,taste ; pressed key to LEDs
out PORTB,mpk
pop mpk ; Return from Interrupt
out SREG,mpk ; restore Status-Register
reti
tc0ci:
ldi mpr,0xFF
out PORTB,mpr
reti
tc2ci:
ldi mpr,0xAA
out PORTB,mpr
reti
test:
; LDI mpk,0x0F
; OUT DDRB,mpk
; LDI mpk,0xF0
; OUT PORTB,mpk
reti

http://www.avr-asm-tutorial.net/avr_en/source/TESTKBD.asm1/20/2009 8:01:43 PM
Guestbook at avr-asm-tutorial.net

Main ==> Guestbook

Guestbook at avr-asm-tutorial.net
I disabled automatic processing of entries in my guestbook due to those silly email-collectors and
spam scripts. Does somebody ever buy something from guys that spam email accounts or
guestbooks? I personally know nobody, do you?

If you like to be listed here, please sent me a mail with a) your name, b) your email address, c) the
text, to info at avr-asm-tutorial.net. I enjoy and appreciate this, and will be happy to enter your text
here.

Date/Time # eMail Name Text


Mr. Have a good day. Very good
site! I liked the Akkuload project.
Maybe a translation of
"Akkulader_Beschreibung.pdf"?.
17.03.2008 hsegurak
Maybe another projects to learn
um 174 @ Hector
more? Also downloaded the
01:34:18 gmail.com
Beginner's course, english, PDF.
Happy to found this site.
Regards from LIMA - PERU
Hector
28.12.2007 info Vielen Dank für die geleistete Arbeit.
um 173 @ n3or Das ASM-Einsteigertutorial ist echt
00:05:42 n3or.de spitze! Viele Grüße, n3or
This is one of the best and most
helpful AVR-asm on-line tutorials
10.09.2007 admin I've ever found. Excellent language
um 172 @ Robert and examples. Great respect for the
03:06:43 ematma.pl author as he apparently is a great
proffesional, tutor and example to
follow. Congratulations :)
Alle Achtung! Das Programmieren
an sich ist schon eine Kunst. Anderen
22.06.2007 lightup
Menschen eine solche Fülle
um 171 @ Designerboy
Informationen und Material geordnet
20:02:46 onlinehome.de
und übersichtlich zur Verfügung zu
stellen ist schon fast edel :-)
18.06.2007 zone_subzero Very good site! Well done! I am
um 170 @ procesorek :-) impatiently waiting for new articles.
20:52:23 onet.eu High regard.
04.06.2007 ikke
um 169 @ Ikke Danke für die Arbeit ! *Thumbs Up*
14:42:06 web.de
Wirklich eine Großartige seite !!!!!!!
Ich finde es echt wunderbar und
bemerkenswert von ihnen das sie sich
29.05.2007 Patrick.Schnedl
so viel zeit genommen haben diese
um 168 @ Patrick
seite zu schreiben .... in welchem
20:27:48 austriamicrosystems.com
Detail + die ganzen Bilder und und
und VIELEN DANK ! *Standing
Ovation*
Hello Gerhard I'am very glad to see
12.05.2007 davor66
nice electronic, informatic and ham
um 167 @ Davor Kordic
site on the internet. Congratulations
12:47:10 yahoo.com
Davor, 9A4KJ
Wow, hammer Seite, aber vor allem
knie ich mich nieder und sage
'Respekt' mit Bewunderung, da es so
eine Monsterarbeit war alles hier
01.03.2007 test Beschriebene erlernt zu haben.. Ich
um 166 @ Lev dachte Assembler wäre wirklich nicht
19:34:32 test.de sooo schwer, muss aber gestehen
dass gute physik und
elektronikkenntnisse wirklich nicht
schaden würden. In diesem Sinne
tschüss! LG lev
30.01.2007 zapsmith Very impressive site,good to see
um 165 @ Ian Smith work shared,and very helpful for a
22:30:20 blueyonder.co.uk defector from PIC microcontrollers!
Hi, eine wirklich einmalige, klasse
Seite. DANKE! Ich bin so begeistert,
dass ich mir soeben das Starterkit
STK500 bestellt habe. Ich habe zwar
vor 17 Jahren mal Assembler
27.01.2007 l_kriegerow
"gelernt", aber mittlerweile alles
um 164 @ LotharK
wieder vergessen. Irgendwie hatten
20:03:21 gmx.de
mich andere Programmiersprachen
fasziniert. Obwohl ich nun schon
viele Jahre als Programmierer
arbeite, kostet es mich einige Mühe,
sich in ASM einzudenken.
Vielen Dank für die tolle
26.01.2007 UlrichLindau Internetseite ! Meine Kenntnisse in
Ulrich
um 163 @ ASM. sind damit erheblich besser
Linndau
06:25:33 T-Online.de geworden. Mit freundlichen Grüßen
Ulrich Lindau
hallo - diese seiten sind eine primas
schule für mich um sich mit
assembler zu beschäftigen.werde sie
07.01.2007 koepplmike wärmstens empfehlen,hoffe das die
um 162 @ mike köppl homepage so lang wie möglich
09:16:44 aol.com erhalten bleibt.habe selten so gute
seiten im net endecken können.danke
und weiter so gruß mike aus
altlußheim
Hello I am very interested in
programming AVR microcontrollers.
Let me know if you or someone have
27.12.2006 pabloorell
information about building the
um 161 @ Pablo
programmer software with Delphi,C+
21:41:36 gmail.com
+ or Visual Basic . Your website is
very helpfull Thanks Pablo Chile
South America
14.12.2006 rexwilliams I appreciate the help you have given
um 160 @ Rex Williams with the AVR tutorial very much,
18:08:45 blueyonder.co.uk many thanks, Rex.
02.12.2006 eduardo
Eduardo M. From Brasil Congratulations [Meus
um 159 @
Pimentel Parabéns] Eduardo
14:24:36 tecblue.com.br
Hy ! Sehr schön weiter so ! MFG
25.11.2006 blancohombre
Anton PS: Suche einen assembler
um 158 @ anton
bzw. dissambler speziell für den
12:13:46 hotmail.com
AT90SC6464.
12.11.2006 sibon29
um 157 @ mehdi
21:36:08 yahoo.com
Estimated teacher, I was a pupil of
the National Autonomous University
of Mexico "UNAM", and I have
considered very useful did of the
24.10.2006 sarumo74 knowledge of my companions of
Saul Ruiz
um 156 @ your handbook, I linking your site in
Mora
06:09:57 prodigy.net.mx the following direction. http://www.
ingenieria.unam.mx/
biblioteca_digital/ biblioteca_general.
php Thank you for your work and
time.
I am Jeshu Chakrabarty. I am from
19.10.2006 mails4_jeshu India. I am trying to learn AVR of
Jeshu
um 155 @ my one & i found your site exrimly
Chakrabarty
12:39:47 yahoo.co.uk usefull I hav downloded the site
Thanks for Providing it!! Jeshu
05.10.2006 order Tolle Seite, Super Erklärungen, mal
um 154 @ Matthias sehen wie lange es dauert bis mein
23:32:07 ledstyle.de (gerade gekauftes) STK500 brennt. ;-)
29.09.2006 karsten.eppert
Karsten Kein Kommentar. Einfach Klasse für
um 153 @
Eppert Einsteiger. 73 Karsten DK4AS
22:08:21 web.de
Prima Seite für ASM-Einsteiger. Bin
23.08.2006 dl1dmw ja BASCOM-AVR Fan, aber etwas
um 152 @ Michael ASM kann nicht schaden. Also
10:08:06 darc.de vielen Dank für die gute Arbeit an
Ihrer Homepage.
Vielen Dank für die viele Mühe,die
02.08.2006 nikolaus.bartels Sie sich gemacht haben, um anderen
Nikolaus
um 151 @ die Möglichkeit zur Weiterbildung zu
Bartels
19:08:34 gmx.de geben. Mit freundlichem Gruß,
Nikolaus Bartels
28.07.2006 Nik
um 150 @ Nik Hello! I'm Nik! Nice site!
10:04:57 mail.ca
27.07.2006 Karter
Hello! I'm Karter! I wana talk you
um 149 @ Karter
something, please mail me.
18:30:38 mail.ca
i want to connect a 16 Char x 2 Line
LCD to a Atmel 8 chip,but i don't
05.07.2006 202054373
know how initilize the LCD,do you
um 148 @ owen
have any source code(Assembler) to
10:36:05 cput.ac.za
do that? if you do,could you mail me
where i can find it,please!
19.06.2006 ldark
um 147 @ Ldarko hi very usefull site :) !! thanks
23:07:34 poczta.onet.pl
17.06.2006 boblock
Roberto Good job, good man. Thank you, my
um 146 @
Locks AVR teacher.
16:35:35 yahoo.com.br
Jo fetttttt, besten Dank für http://
14.06.2006 okolyt
www.avr-asm-tutorial.net/avr_de/
um 145 @ Okolyten Bob
keypad/keyboard.html viele grüße
09:17:04 bob.de
auch von Fritze und Kalle
Thanks for gavrasm. I succesfully
compiled it on Mac OS X using free
pascal. I am developping equipments
04.06.2006 azumi for scientific research and looked for
Kazuhisa
um 144 @ atmel-style assembler on OSX (not
Azumi
06:00:29 eng.hokudai.ac.jp gcc-style). Your gavrasm will help
my research so much. Thank you
again !! ( Kazuhisa Azumi (from
Japan)
Hi I am Suresh. I am new to AVR
controllers. Your website proved
instrumental for me in working on it
03.06.2006 suresh_16001
for the first time. You are a true
um 143 @ Suresh
guide for me. Thank you very much
19:07:40 yahoo.com
for the support in the form of this
information you extended. warm
regards suresh
01.06.2006 hamidpac3
hallo ic heise hamid aus dem iran pls
um 142 @ hamid reza
help me about ac motor control
15:33:01 yahoo.com
16.04.2006 ih4ven0email Eine wirklich klasse Seite! Der Inhalt
um 141 @ 4t ist vom aller feinsten! Danke! Gottes
15:23:29 hotmail.com Segen & ein frohes Osterfest! 4t
10.04.2006 jm_corona64 Excelent job creating this page, I love
um 140 @ Jose it. Thank you for sharing your
05:25:55 hotmail.com knowledge.
Thank you for building this site. I
25.03.2006 lmachu
MACHU have put many answers in front of
um 139 @
Laurent my questions. It is now a pleasure to
07:36:49 waika9.com
program my AVRs Thank you
Ich glaube mein Hauptproblem liegt
darin dass ich ein konkretes ziel habe
welches ich mit dem kopf durch die
wand erreichen wollte. Ich hab mir
einfach das meiner meinung nach
optimalste Paket ausgesucht um
schnell an mein ziel zu kommen ohne
im geringsten zu ahnen was ich mir
da auflade. Also werde ich von vorn
anfangen und einfach nur spielen.
Alles mal ausprobieren, auch
19.03.2006 zippel
Roland assembler. Die Hardware ist mit
um 138 @
Tennert Mega 8 mehr als ausreichend für
18:10:59 datel-dessau.de
meine zwecke, wen ich da nicht
schon wieder falsch liege. Ich werds
ja merken. Also dann, vielen dank
und sollte ich in ein paar monaten
mein erstes projekt fertig haben meld
ich mich noch mal. Ich bleib dran.
Die elektronik hab ich mir auch
selbst beigebracht. Tschüß und nach
möglichkeit nicht solch schwierigen
fälle wie mich Roland Tennert
zippel@datel-dessau.de
Hi i would just like to thank you for
putting together such a good manuael
16.03.2006 deanobaxter
on AVR programming it is really
um 137 @ Dean Baxter
dawnting for me and your guide
06:26:58 hotmail.com
makes it much better Thanks a
million Dean
Hallo, ich finde Ihre Webseite sehr
13.03.2006 korte2004
informativ und interessant. Mit
um 136 @ Korte
freundlichen Gruessen aus Berlin
12:59:06 yahoo.com
Korte
So, Hr. Gerhard Schmidt ! Habe mir
just das STK 500 bestellt, um mit der
ASM Programmieren so richtig
loslegen zu können. Habe mich
natürlich vorweg mit mit den
Datenblättern der Prozessoren
beschäftigt. Keine Ahnung wie lange
es dauern wird bis die
Programmierung leichter von der
Hand gehen wird, aber als erstes
Projekt möchte ich mich gerne in das
Projekt "Metallsuchgerät"
12.03.2006 Roland.Stotz
Einarbeiten. Vorerst recht einfach
um 135 @ Roland
gehalten, jedoch in späterer Folge
16:39:29 infineon.com
sollte der Speicher recht
Raumgreifend mit Nullen und Einsen
gefüllt werden :-) Diese Seite ist bis
DATO mein persönliches
Aushängeschild in PUNKTO
Assembler Programmierung. Also
weiter so ! Danke nochmals für diese
Sehr Informative Seite. Ist ja auch
der GRUND warum ich mit der
Programmierung angefangen habe.
Freue mich schon auf das Board. mfg
Roland
hello..sir i am student collage on
Indonesia. i am, so interest with avr. i
02.03.2006 fajrul_ilhami have the problem about how to use
um 134 @ Fajrul Ilhami software codevision. if you have any
19:58:39 yahoo.com e-book about bascom, or C language.
thanks for u attention.. i hope u help
me ... thanks best regard, fajrul
Lieber Webmaster! Ich habe grossen
Respekt vor Ihrer Arbeit und möchte
Ihnen auf diesem Weg danke sagen
für Ihre Mühe! Ich beschäftige mich
seit meinem 12 Lebensjahr mit
Assembler Programmierung
23.02.2006 stevie72
(6502,8080,8085,Z80,80C535,
um 133 @ Stefan
MC68000er) und nun auch mit PIC
13:44:34 gmx.de
bzw. AVR. Ihr Kursus ist sehr leicht
verständlich und Übersichtlich
gestalltet. (Heute bin 33 Jahre
Jung :) ) Vielen Dank nocheinmal!
Schöne Grüße aus Köln. Einen
schönen Tag noch! Stefan
Hello, I'm just returning to using
assembler after 20 years! (6800 and
8080). I am reading your math
07.02.2006 terry
routines to try and understand how to
um 132 @ terry rose
use fixed point math with the AVR.
17:03:37 terrywrose.plus.com
Thank you very much for your time
to put this excellent web site
together. Regards, Terry Rose
Glückwunsch und danke für diese
Seite. Ich hab hier so ziemlich alles
02.02.2006 ginotronik
Wolfgang gelernt, um meinen Roboter zu
um 131 @
Geenen programmieren. Und natürlich
22:10:15 web.de
diverse andere Projekte. Wolfgang
alias Gino
a very useful site for me! all essential
07.01.2006 u741koolhip
information about learning AVR is
um 130 @ steve
here well orgarnized. highly
01:46:41 hotmail.com
recommend this site!
Also ich hab in der Berufsschule
angefangen Assembler zu
programmieren und ihre Seite hat mir
29.12.2005 Juergen.Jungnickel
Jürgen sehr dabei geholfen den Schulstoff
um 129 @
Jungnickel besser zu verstehen. Darum wollte
22:12:50 o2online.de
ich ihnen danken für die tollen
Beispiele und Erklärungen.
Danke!!!!!!!
Hi! Your page is wonderful! I read
19.12.2005 atommann
the article about the R/2R-network,
um 128 @ Atommann
and have done some experiment.
03:35:30 gmail.com
Successful! Danke!
10.12.2005 vignesh.e Excellent effort to explain the most
um 127 @ Vignesh sought info for any microcontroller!!
16:28:06 gmail.com Cheers, Vignesh
Vielen Dank für das PDF des AVR-
07.12.2005 a ASM-Tutorials. Danke! Danke!
um 126 @ Georg Danke! Nach so etwas hab ich
20:03:35 bb.cc gesucht und ich hab's gefunden.
Danke!
06.11.2005 gerdstrecker Will mich mal etwas intensiver mit
um 125 @ Gerd Strecker DCC für Spur N (Einbau in BR80)
08:07:29 freenet.de beschäftigen.
Hallo Gerhard ! Ein gelungener
Auftritt, mit gut gestaltetem Inhalt
für alle Freunde der Atmel-
16.10.2005 DAschm0912
Dieter Controller und deren
um 124 @
Aschmann Programmierung. Sicher lich immer
10:35:30 aol.com
mit viel Mühe verbunden das Ganze
so aktuell zu halten. Weiter so, ....
Dieter
thanks for the information, i'm a
07.10.2005 nickelkitten910
newbie on programmation and i hope
um 123 @ Guadalupe
to learn from your tutorials. greetings
17:36:29 yahoo.com.mx
from Mexico
05.10.2005 jaigodara u really done a great job by providing
um 122 @ jai parkash such information on AVR mc..its
20:53:47 gmail.com really wonderfull.. thankssss
Tolle Seite, hier habe ich alles
04.10.2005 dg8yho gefunden, was ich als Newby
um 121 @ dg8yho brauche. 2 Tage Google vorher war
19:38:27 test.de nicht so erfolgreich! Danke nd ´73 de
Jan DG8YHO
Guten Tag, alles schön und gut, aber
12.09.2005 d.kuckenburg was ich nirgends finden konnte: für
D.
um 120 @ was steht die Abkürzung AVR ? Gibt
Kuckenburg
09:18:53 gmx.de es eine Erklärung ? Vielen Dank im
voraus. Gruß D.Kuckenburg
hallo! Ich möchte mir einen mc
01.09.2005 killss70 (AT90S2313) zulegen... Aber wo
um 119 @ cooli kann ich Sachen anschließen? Zum
20:26:36 yahoo.de Beispiel wo schließe ich eine LED
an? An welchen pins? MfG, Cooli
Für diese Seite haben Sie ein dickes
28.08.2005 spam
Lob verdient. Sie hat mir den
um 118 @ Sascha
Einstieg in das Thema sehr einfach
01:35:25 mail.com
gemacht. Vielen Dank
Advice pease, how to read data from
device connected to PD*, but we
need to read not answers from device
22.08.2005 sinbaal
connected to PD*, and his "hex"
um 117 @ Delphi
code, which was written in external
08:07:05 mail.ru
chip by programmer. Read from
some address on connected chip.
Thanks
18.08.2005 fabianschuiki
um 116 @ Schui Super Seite! Echt Toll! Gruss, Fsch.
15:30:38 bluewin.ch
Hello I want to compare a register
value with constant 2,if it is equal
15.08.2005 marwa_mekki
then branch.When i do the following:
um 115 @ marwa mekki
asm("CPI R22,2"); asm("BREQ 5"); i
11:06:22 hotmail.com
get a copilation error: Error: operand
out of range: -193
Hello there, I am from Mexico, I am
a student and I speak Spanish anda I
am leranning English and German
02.08.2005 nitramgv and ATmega8535 too :). Now, Im
um 114 @ Pedro Martin studying master career. I could see
19:48:46 hotmail.com your personal website and I liked it
so much. Saludos desde México... I
would like to do a doctor study there
in German.
02.07.2005 saman.kh Sehr schoen gemachte Seiten Ich
Zdenek
um 113 @ vuensche Ihnen viel Spas in Ihre
Simunek
20:33:34 atlas.cz Arbeit. Gruss von Simunek
Very good and well documented.
03.06.2005 ffoxtrotjunk
Carlos Explanation with easy and detail. A
um 112 @
Almeida must read.... Thank you
14:44:50 yahoo.com
ffoxtrotjunkatyahoo.com
Gott was für eine Hilfe..ich bin echt
18.05.2005 sam104
Karsten froh über die Seite hat mir den
um 111 @
Scholz Anfang echt erleichtert und heute ist
06:10:58 sam104.de
alles so einfach.
29.04.2005 matagnex I thank you very much for your good
Xavier
um 110 @ tutorial. I teach the 90s8515 and it
Matagne
10:19:07 yahoo.fr helps me. Xavier
24.04.2005 zerpo
um 109 @ zerpo Great site, everything's cool!
09:43:30 poczta.onet.pl
Toll gemacht Ihr AVR- Assembler
09.04.2005 DAschm0912
Dieter Tutorial, erspart dem Anfänger wie
um 108 @
Aschmann mir teure Bücher. Eine Bitte machen
17:45:57 aol.com
Sie weiter so.
17.03.2005 sirios
Dimarakis
um 107 @ Hello from Greece. Thanks.
Thanos
20:37:11 otenet.gr
Thanks for the opportunity to learn
06.03.2005 a.hellebaut assembly for the ATMEL-chips. I
Armand
um 106 @ have age 79 but I will try it./ I have
HELLEBAUT
16:27:01 skynet.be good young compnanions Best
regards. ON4TL;
sehr brauchbare infos für anfänger,
25.02.2005 spam
und mal wieder ne gelegenheit die
um 105 @ Schaf
grundlagen aufzufrischen. thx lg
16:18:52 spam.schaf.at
Martin
04.02.2005 PE1NPG Jean-Pierre
Very helpfull site for me, thanks for
um 104 @ van der
putting in all the effort!! Jean-Pierre
14:18:33 amsat.org Zanden
18.01.2005 meser
um 103 @ Srdjan thanks for knowledge Srdjan Srbija
09:47:39 ptt.yu
hallo, danke für die prima
16.01.2005 kmund4 aufbereiteten infos und die
um 102 @ Klaus Mund freundlicherweise zum lernen zur
12:58:31 aol.com verfügung gestellten erfahrungen.
viele grüsse aus BY
Eine wirklich tolle Seite. Für
Anfänger wie mich ein absoltes muß.
05.01.2005 Hightech20002002
Sehr gut verständlicher Inhalt. Werde
um 101 @ Uwe Kunrad
ich auf jedenfall weiter empfehlen.
16:54:30 yahoo.de
Danke nochmal für diese erstklassige
Hilfestellung Gruß Uwe
31.12.2004 michael-guenther
Michael Tolle Seite, da macht der Anfang
um 100 @
Günther Spass.
18:03:54 onlinehome.de
You have a wonderful website! I
have been wanting to know how to
apply my knowledge of
06.12.2004 michael.docholiday
programming to interface with
um 99 @ Michael King
hardware for a long time. Any other
03:40:34 gmail.com
suggestions you might provide to get
me started would be great! Thank
you.
04.12.2004 John
um 98 @ John best in class tutorial! excellent work!
12:22:39 rogers.com
It's an excellent web site,
30.11.2004 aesv
congratulations a bunch of resources
um 97 @ alfred salazar
to keep on the way with ATMEL.
08:31:07 yahoo.com
Afredo Salazar UNI - Lima -Peru
Hallo Tolle seiten echt super gemacht
29.11.2004 pewok1
mach weiter so ich schaue mal
um 96 @ Peter
wieder vorbei MfG Peter http://www.
04:24:48 gmx.de
versandhandel-woike.de
Dein Tutorial ist wirklich
verständlich und ausführlich. Bei
vielen anderen Anleitungen werden
oft feine Details, oder genaue
27.11.2004 Voyager
Erklärungen von Schaltungen weg
um 95 @ Frank
gelassen. Aber bei deinem
08:24:53 mail.isis.de
Einstiegskurs ist alle inklusive. :-)
Ich kann mich noch nicht zwischen
einem PIC oder Atmel Controller
entscheiden...
21.11.2004 Adank Tolle Seite, ich bin sehr dankbar über
Michael
um 94 @ die überaus hilfreiche AVR Infos
Adank
09:29:40 (ohnedas)iba-lg.de schöne Grüße aus Lüneburg
Echt klasse Mikrocontroller
14.10.2004 ThommyMaier Einsteiger Seite!! Gut kommentierte
um 93 @ Thommy Beispiele mit Bildern auch die ADU
12:36:39 web.de kommt nicht zu kurz dickes Lob...aus
Freiburg!! Thommy
In french Viren means Virus but
don't fear, I am a simple Guy. Your
26.09.2004 Virenchocha tutorials are just great, I have got my
um 92 @ Viren Chocha feet wet, now I'm gonna test newly
21:47:41 msn.com acquired knowledge(by your grace)
on hardware. Thanks a lot, thanks a
lot raised to infinity.
Thanks very very much for the
excellent tutorial, it's indespensable !
16.09.2004 kumar_ramanathan
Krishna I got started in a few days flat, I'm
um 91 @
Kumar already writing some of my own
08:07:34 yahoo.com
code, albeit very basic code. But
thanks a lot, Danke Schon !!
The "Beginners Introduction ...to
ATMEL-AVR..." was just what I
10.09.2004 larmakle needed. Perfect! Now I need to find a
um 90 @ Magnus place where I can find an example on
19:52:18 hotmail.se how to "program" the UART so that I
can talk RS232 from AVR to PC.
Best Regards Magnus
09.09.2004 nichtimnetz
Klasse Seite - Ich leg jetzt mit atmel
um 89 @ Benjamin
los...
17:24:28 email.com
das tutorial ist echt umfangreich..
danke! so viel mühe :) damit kann
02.09.2004 dave_in_the_grave man auch etwas komplexere sachen
um 88 @ dave w. machen, als leds einschalten hehe..
14:31:56 gmx.de ich hocke grade an ner luxus-
lüftersteuerung.. dave überlingen,
bodensee
Hi ! I am in my first steps with
microcontrollers design and I was
26.08.2004 paulinhovjr
looking for help and tutorial, then, I
um 87 @ Paulo
found your homepage. Thanks for
02:04:42 ig.com.br
your help. May GOD bless you Paulo/
Brazil
Sehr schoene Seiten. Habe schon viel
von den AVR Angeboten abgesaugt
12.08.2004 Ralf
und gelernt. Toll, dass sich jemand
um 86 @ Ralf Zaeper
hinsetzt uns sich so viel Arbeit
03:08:39 zaeper.de
macht. Guesse aus derzeit Houston,
Texas, Ralf
11.08.2004 there Wielen dank fûr Deinem seiten!
Rauli
um 85 @ programs.asm und Deinem exampler
Lauhanen
14:53:26 is.no macht spass! Rauli, Finnland
Ich bin sehr dankbar für ihre Seite,da
27.07.2004 king-big-alex sie mir viel weiter geholfen hat,gut
Ewert
um 84 @ eingerichtet ist,einfach Klasse und in
Alexander
12:28:13 web.de deutsch geschrieben ist. Es lebe
LINUX. Es lebe die FREIEIT.
Hallo Toll, Ihre Seiten!!! Muss mir
22.07.2004 avr
gleich mal den AVR-Kurs
um 83 @ Robert
ausdrucken und durchlesen :-) Alles
03:32:44 pukshofer.com
Gute noch und viel Gesundheit :-)
THIS PAGE IS AWESOME, THIS
12.07.2004 jacuinde Oscar IS THE FIRST TIME I LEARN
um 82 @ Jacuinde ASM AND I LEARN TO
20:49:23 telnor.net Beltran PROGRAM A AVR AND ITS ALL
CLEAR LIKE WATER
This message is written in Dutch:
17.06.2004 dionjolink Leuke website, goede leerzame
um 81 @ Dion Jolink tutorials. Ik wacht met smart op de
15:59:26 planet.nl nieuwe:P Groetjes, Dion www.dd-
software.net
12.06.2004 gertvdmeij
Gert van der
um 80 @ Thanks for the nice tutorial!
Meij
14:46:39 planet.nl
21.05.2004 sarumo74 Dear Senor Schmidt. Your tutorial its
Ruiz Mora;
um 79 @ best tutorial over AVR. Muchas
Saul.
20:54:08 hotmail.com gracias from México and U.N.A.M.
04.05.2004 ralcocer I have put a link on my website http://
Rafael
um 78 @ ralcocer-avr-projects.com Come join
Alcocer
01:52:53 ralcocer.cjb.net my webring Rafael Alcocer
ach noch was : das erfolgreiche
29.04.2004 messerjokke
alexander projekt ist auch dein verdienst ....
um 77 @
schmidt http://fireback.bbbk.du.nw.schule.de/
21:36:21 nexgo.de
danke nochmal , gruss alex
DANKE !!!! sie haben mir
29.04.2004 messerjokke buchstäblich den arsch gerettet !!!
alexander
um 76 @ (bbbk - technikerschule duisburg, nur
schmidt
21:32:22 nexgo.de noch 47 tage bis zur
abschlussklausur !!)
Ich bin gerade dabei mich für einen
Microkontroler zu entscheiden. Ihre
Seite hat sehr dazu beigetragen das
15.04.2004 andreaswohlrabvarioboard
Andreas ich misch warscheinlich für die AVR-
um 75 @
Wohlrab Serie von ATMEL entscheiden
09:55:49 t-online.de
werde. Ich hätte gern gewußt woher
die Platiene der Platine mit dem LCD-
AVR stammt.
30.03.2004 creek55
um 74 @ Nick Wolf Thank You !
18:23:19 yahoo.com
Hallo, bin gerad dabei den
29.03.2004 service
Anfängerkurs (quer-) zu lesen. Prima
um 73 @ Thomas Horn
geschrieben. Gute Arbeit. Beste
17:11:57 data-complex.net
Grüße Tom
Alle Achtung, eine sehr gut
durchdachte und übersichtliche
Website. War 'ne tolle Hilfe. Was mir
23.03.2004 kll1
Karlheinz noch fehlt ist die Möglichkeit den
um 72 @
Storck Assembler-Quelltext in mehrere
10:09:13 online.de
Dateien zu splitten, so wie man das
üblicherweise in C macht. Gibt's da
Vorlagen? Viele Grüße Karlheinz
Hallo, sehr schoene seiten zum thema
16.03.2004 bomer
avr. der kurs ist ja das beste was
um 71 @ B.Boemer
bisjetzt gesehen habe. mach weiter so
12:35:09 uni-muenster.de
Gruss Bernd
Nice Homepage. I searched a long
13.03.2004 jonas_kneer
time after something like that and i´m
um 70 @ Jonas
very happy that i have found this
21:42:42 lycos.de
great page. Thx a lot for this page.
i'm a student in one of Indonesian
Univ. i'm sorry i can't use dutch
language, so i use english i just
wanna ask to you how can we make a
fire fighter robot using micro
controller, because i'm still confuse
22.02.2004 avissena_ken
to aplicate the microcontroller system
um 69 @ widyasmoro
in my project that is fire fighter
08:04:14 yahoo.com
robot, of course in a minimum budget
please give me the clear explanation
and step by step from the first step
until finish, it will be better if you
can attach picture in it i'm waiting for
your answer , thank you very much
Ich verwende das AVR-ASM-
Tutorial in einer schriftlichen
13.02.2004 hans.hafner
Facharbeit, wobei ich die allgemein
um 68 @ Hans Hafner
üblichen Zitierregeln einhalte und auf
10:35:49 hit-htl.at
den Autor verweise. mfG Hans
Hafner
07.02.2004 rdcastellano
Thank you for the help this site gives
um 67 @ Ronnie
me
16:29:37 earthlink.net
05.02.2004 info
Great AVR turorial. It's really a good
um 66 @ Koen Postma
starting point for my students!
20:39:42 postmaelectronics.nl
Lieber Herr Schmidt, sehr gutes
Material, sehr praxisorientiert -
Glückwunsch! Habe vor 25 Jahren (!)
Z80 programmiert, bin mit AVR
"Wiedereinsteiger". Die Sache macht
mir riesigen Spaß: habe hier AVR-
Studio in einer Mac-Emulation zu
laufen, was nach 14 Tagen harter
Arbeit auch endlich trotz USB-
17.01.2004 hhstamer
Hans-Hasso Seriell-Adapter mit "doppelter
um 65 @
Stamer Emulation" - der Mac emuliert eine
14:50:24 gmx.de
RS232-Schnittstelle über USB und
außerdem einen PC, der diese SS
untergeschoben bekommt und brav
darüber ausgibt - funktioniert:-)
Grüße - Hans-Hasso Stamer,
Musiker, früher mal als Ingenieur im
Schulungszentrum von "Robotron",
zuständig für MRES 20, ein
Mikrorechnerentwicklungssystem.....
Hallo OM Schmidt, Ihr AVR-
Anfängerkurs ist echt prima. Ich habe
jetzt den 68HC11 verlassen und bin
14.01.2004 dl8oai
zu den AVR's gekommen. Alles was
um 64 @ Volker Herrig
man so schnell mal für AVR-
22:42:13 darc.de
Assembler so wissen muss habe ich
von Ihnen. Besten Dank. 73 de
Volker, DL8OAI, Z47
Hallo Gerhard, eine sehr gute Seite.
Sie hat mir als Anfänger sehr
geholfen. Allerdings habe ich die 2
(*4*)-Zeilige LCD (204) im 4-bit-
Modus nicht zum Laufen gebracht.
Es wurden nur Zeile 1 und 3
angezeigt. In den einschlägigen
Foren sind nur unzureichende Infos
erhältlich. Den entscheidenden
Hinweis bekam ich dann aus der
Schweiz: Man muß die 2-Zeilen-
Initialisierung 2* durchführen! Ich
hab es einfach ausprobiert und es
funktionierte. Dann hat es mich aber
14.01.2004 w.jahn gepackt und ich wollte wissen:
Wolfgang
um 63 @ Warum? Ganz einfach: Das Display
Jahn
06:36:52 addcom.de initialisiert im 8 bit-Modus und die
Umschaltung erfolgt im bit #3
(unteres Nibble). Aber genau das ist
bei mir hardwaremäßig (4 bit
Ansteuerung) auf 0 gelegt. Es wird
also nie auf 2 Zeilen initialisiert. Das
erfolgt erst bei der angesprochenen
Befehlswiederholung. Beim ersten
Mal wird in 8 bit Ansteuerung auf 4
bit umgeschaltet, beim 2. Mal erfolgt
die Umschaltung im 4 bit Modus auf
2 Zeilen. Jetzt ist eigentlich nur noch
offen, was mit dem zweiten Nibble
des ersten Befehls passiert. Viele
Grüße aus dem Frankenwald W
07.01.2004 adsf Hi!!!! Ich bin ein Atmel-Freak, es
um 62 @ lanny.ch sind wohl die besten uC's! Gruss aus
22:47:05 asdf.ch der Schweiz dani
26.12.2003 supagu
Fabian Exellent website, very helpful when
um 61 @
Mathews learning AVR :)
13:53:27 hotmail.com
09.12.2003 mokdadr
um 60 @ Mokdad raed
11:44:44 yahoo.de
Ich habe eine Seite zum Assembler
lernen gesucht und muss sagen: Das
08.12.2003 NoValid
ist sie ! Top gemacht und super
um 59 @ Markus
erklärt ! Einziger Kritikpunkt: ein
16:19:35 Address.de
paar Rechtschreibfehler Top Seite !
Werde ich weiter empfehlen !
07.12.2003 gorbhag
Very nice and useful page! The best
um 58 @ Artur
for beginners in avr-world..
22:37:59 o2.pl
I am trying to set up the 2 line LCD
display for the STK500,using
04.12.2003 carrolld
Lcd4IncCE.asm,but get an error on
um 57 @ Dan Carroll
compiling "can't find Lcd4Inc.asm, I
14:31:56 lsel.ns.ca
cannot find this file, is it available?
Regards Dan
14.11.2003 scott.pinkerton This site is just about everything I
um 56 @ Scott need right now to move into ASM for
00:25:04 adl.lep.com.au Micro Processors. Well done!
Hallo, ich habe Deine Seite
besichtigt. Eine prima Leistung ! Ich
06.11.2003 finanse
Piotr glaube, sie wird für mich für lange
um 55 @
Kaczecki Zeit die Nummer 1 werden ! Ich
17:41:09 leier.tarnow.pl
melde mich noch irgendwann. Grüsse
Piotr aus Polen (auf Deutsch: Peter)
05.11.2003 elwinulje
um 54 @ Elwin Great site! Keep up the good work =)
12:12:41 hotmail.com
Der Assemblerkurs ist Klasse nur tu
31.10.2003 C.R.Z ich mich halt sehr schwer. Wie heist
Zellmeier
um 53 @ es so schön! Kunst das kommt von
Rupert
09:51:07 t-online.de können, käme es von wollen so hiese
es Wunst
I am going to learn AVR for the first
31.10.2003 coronapune time. It seems your pages will reduce
um 52 @ Vasant Nehete my faltering steps in the beginning.
06:12:23 vsnl.com Thanks for putting correct material in
less memory. vasant Nehete
hello, i would like to thank you for
30.10.2003 adrianaadl this wonderful page. it's great for
um 51 @ adriana people trying to find their way
15:59:47 hotmail.com through assembly language. i am
very grateful to you.
I am looking a good and nice web for
19.08.2003 my8051_ph the AVR rto widen my 8051
um 50 @ F. Dandy knowledge and I found a cave with a
12:23:52 hotmail.com lots of GOLD --- a lot for the AVR
beginners like me. Thanks a lot.
Das ist ja eine ganz tolle Anleitung...
Ich fange gerade erst mit dem
17.08.2003 kgrun99999
ATmega an und dank vieler Tips und
um 49 @ kurt
Beispiele wirds bestimmt gut
20:53:52 aol.com
klappen.. Vielen Dank für diese
Arbeit !!
14.08.2003 c1tan
Very good and interesting, keep up
um 48 @ CS Tan
the good work. Good luck.
18:24:48 plymouth.ac.uk
04.08.2003 squall_here i want to know about a
um 47 @ squall mocrocontroller atmel AVR,
17:51:36 yahoo.com aplication, and how to use it
11.06.2003 Bertram.Energietechnik
Detlev
um 46 @ vielen Dank für die Einführung
Bertram
21:56:57 t-online.de
Danke für das Tutorial, ich würde
04.06.2003 Klaus.lukkes wahrscheinlich sonst nur Bahnhof
um 45 @ Klaus verstehen. Wenn ich mal weiter bin,
15:42:05 aht-partner.de stell ich gerne meine Erfahrung auch
zur Verfügung. Nochmals Danke.
Hello I just found your site and it has
02.06.2003 hogantech already answered a few of my
Michael
um 44 @ questions. I will give more feedback
Hogan
14:42:45 netspace.net.au as I proceed through the tutorial.
Regards Michael
30.05.2003 j-l-h
sehr gut verständlich saubere Arbeit
um 43 @ Jens Lieberum
Sir/Lady
19:30:37 web.de
Dein avr-asm-tutorial ist das Beste,
was ich jemals in Sachen Assembler
gelesen habe. Der Aufbau dieser
Domain mit allen Querverweisen, die
17.05.2003 juppi Liebe zum Detail und die Kunst sich
um 42 @ Juppi in einen Assembler-Anfänger
12:08:01 gmx.li reinzudenken, übertrifft alles, was ich
bisher gesehen habe.(Ich habe vor 25
Jahren mit Cobol und Fortran
angefangen, dann C etc. etc.)
Kompliment - Juppi
Ganz tolle Seite, echt spitze.
18.04.2003 spam Besonders hilfreich fand ich konvert.
Andreas
um 41 @ asm, von der Routinen habe ich mir
Weber
01:44:05 tech-chat.de echt sehr viel abgeschaut. Weiter so !
Gruß Andy
25.02.2003 Gerry.keely Very good introduction to AVR
um 40 @ Gerry Keely assembly language programming
12:15:39 esbi.ie Many Thanks Gerry
15.02.2003 Albert-Hildebrand
Albert
um 39 @ Einfach super gemacht; Respekt!
Hildebrand
23:29:36 t-online.de
10.02.2003 hans.demharter
hans-
um 38 @ prima weiter so dl5mfo
demharter
19:37:04 t-online.de
10.02.2003 hans-peter.Demharter
Hans
um 37 @ prima so danke gruß dl5mfo
Demharter
19:34:00 telekom.de
09.02.2003 Uwe Super Seite! Bin schon ganz Karusell
um 36 @ Uwe in Kopf da Anfänger. Komme also
12:30:20 hebels.de öfters vorbei!
I enjoyed learning AVR assembly by
12.01.2003 enowicki using your tutorial. Thank you for
um 35 @ Ed Nowicki taking the time to create these pages
22:06:51 letllc.com and sharing your knowledge. Best
regards, Ed
Hello, Your page is GREAT... just
04.01.2003 customecu
what I needed. I would send you a
um 34 @ Steve
Frauline if I could. :) Happy 2003,
02:00:28 websurf.net
Steve
12.12.2002 vikram_mutneja
are SRAM contents reset to 0 on
um 33 @ vikram
power on reset
19:07:09 yahoo.com

http://www.avr-asm-tutorial.net/gb_new.html (1 of 2)1/20/2009 8:01:52 PM


Guestbook at avr-asm-tutorial.net

Hallo, prima Seite ! Kann schon


29.11.2002 Klaus_Falkenberg
Klaus einiges auf den AVRs, habe hier aber
um 32 @
Falkenberg noch reichlich dazugelernt. Viele
09:09:43 web.de
Grüße Klaus
10.10.2002 birdix
http://Gheos.com/avr :) FREE AVR
um 31 @ RoBSki!
stuff for the masses
14:36:54 hotmail.com
25.09.2002 kiran_mr Thanks for coming out with a
um 30 @ Kiran M.R. excellent website..i am a new entrant
14:23:39 yahoo.com into the AVR world. Regards, -Kiran
07.09.2002 ferlopvi
um 29 @ Flopez Very nice and helpfull site!
21:05:40 earthlink.net
Sehr schöne Seite, gut verständliche
Beispiele. Arbeite gerade an einer
26.07.2002 Hemmecke Fließkommaarithmetik für den AT90.
Martin
um 28 @ Da ich allerdings erst seit 2 Tagen
Hemmecke
08:51:25 fh-swf.de das STK500 habe, dauert es noch ein
bisschen. Sende Euch eine Kopie des
Codes dann zu. Gruß Martin
24.07.2002 bruno.marcio
Im looking for this tutorial so long
um 27 @ Bruno Marcio
time, nice job!! regards,
08:25:04 bol.com.br
Thank you for an excellent tutorial.
John and I are 3rd year students
studying for Bachelor of Information
Technology. We are working on a
02.07.2002 younggl2
Graeme & project using the STK500 AVR and
um 26 @
John had difficulty finding useful
02:18:56 tekotago.ac.nz
information. Your tutorial fills all our
needs excellently. Graeme
Youngman, John Corkery, c/o Otago
Polytechnic Dunedin New Zealand
Great Stuff..I'm heading off into a
mega 8 program with tons of info!
25.06.2002 davidp Not to sure about the pointer *2 and
um 25 @ David Pilote than how you point to the 5th value
19:28:00 osc.on.ca but are using a 10? Could you
explain a little more there (pointer-
register)access. Thanks...DP
Hi! Sorry, but I speak only bad
25.06.2002 mkoala
english :-)). Your Site Is very good
um 24 @ massimo
for beginners! Thank You for your
14:30:40 libero.it
help.
17.06.2002 Aqua-Perl
um 23 @ Werner Bühre Ich bin Anfäger
21:57:54 t-oline.de
21.05.2002 ahuman1
This is the first of it's type that I've
um 22 @ Art Human
seen. VeryGood!!!
19:24:43 netzero.net
Great page thanks for the info, I want
to start programming on AVR's and
so far your page has been very
helpfull. I do have a question about
AVR's and what they can and can't
do. I found a MC68HC11 base PSX
gamepad emulator on the interenet
and this controller is very expensive
10.04.2002 hbelanger
Hugues and hard to source I'd like to know if
um 21 @
Belanger the AVR family can be use to
17:44:55 701.com
duplicate the design and how hard
would it be to port the code... Here's
the url http://www.gamesx.com/
controldata/psxcont/psxcont.htm See
the section titled "A Microcontroller
to Emulate a PSX Controller" Please
be kind and replay ASAP Thanks in
advance Hugues
Tan: I'm trying to get thru to you.
Write me back if this works. Your
email address on your card reads:
08.04.2002 ethomkin
tan@silliksaar.com and this isn't
um 20 @ ethomkin
going thru. I'm at the library and
22:54:59 yahoo.com
someone is helping me but with little
success. Hope you get this. Eunice
Thompson
07.04.2002 bigbud2k
Your page is fantastic...thank you so
um 19 @ fatnbald
much..best information Ive found yet
14:52:52 htmail.com
06.04.2002 frogfot You have the best page ever about
um 18 @ frogfot AVR. Im really thankful for great
10:14:19 hotmail.com help :)
bin schon immer ein neugieriger
Leser für Mikrocontroller gewesen,
31.03.2002 walterjosch
jetzt möchte ich, dank Ihrer Beiträge
um 17 @ walterjosch.de
in der CQ/DL in den praktischen Teil
16:33:58 gmx.de
übergehen, mein call DL3OAZ mfg
Walter
Eine echt super gelungene Seite. Sehr
übersichtlich gestaltet und überaus
27.03.2002 webmaster nützlich. Für Anfänger ideal
Stefan
um 16 @ geeignet! Nur weiter so, schade dass
Steinbach
23:02:00 elektroniktreff.de es nur wenige solcher informativen
Seiten im Internet gibt. Also, weiter
so!!! Thx
Ich habe mir das Beispiel mit der
"Division einer 16Bit Zahl durch eine
8Bit zahl runter- geladen.In welcher
27.03.2002 hesna.ayhan
AYHAN version von AVR Studio3
um 15 @
Engin funktioniert dieses Beispiel.Mit der
15:35:30 chello.at
Version 3.52 geht es nicht,hab es
schon ausprobiert. Hilfeeeeeeeeee !
Bitte Danke.
24.03.2002 sergej.bergmann
Sergej
um 14 @
Bergmann
09:47:49 uni.de
15.03.2002 brooksc
um 13 @ Clive Brooks Excellent work
03:22:56 iprimus.com.au
This is the sort of tuition that I've
been looking for on AVR's As a
13.03.2002 bam
beginner. It fills in a hole between
um 12 @ Rob Mullions
getting the hardware and being able
03:48:32 xtra.co.nz
to actually do something with it
without going nuts. Many Thanks.
Tolle Website. Für Menschen wie
ich, die autodidaktisch AVRs
07.03.2002 sbo
programmieren lernen wollen, eine
um 11 @ Rodrigues
unglaubliche Hilfe. Sehr
06:09:19 aol.com
übersichtlich und
anwenderfreundlich. Vielen Dank.
Thanks man, for a very resourceful
03.03.2002 espenhoel and well written set of webpages! -
um 10 @ Espen Hoel this is absolutely the best instructions
13:42:30 hotmail.com for "beginners" that I've come across
on the net.
26.02.2002 royojt This is an excellent site!! I will be a
um 9 @ Roy Delatore frequent visitor to this site.
03:59:51 yahoo.com MABUHAY!!!
Ich bin Ausbilder im
23.02.2002 utewend
Wolfgang Elektronikbereich, dies ist eine sehr
um 8 @
Sedlmeier gute Bereicherung. Danke für Ihre
13:31:51 compuserve.de
Veröffentlichung
Ich finde es immer wieder
bewundernswert, wie selbstlos
manche Menschen ihr Wissen an
04.02.2002 letsittry
andere weitergeben und dabei noch
um 7 @ Rainer
zusätzliche Arbeit im Erstellen und
21:56:16 gmx.de
Pflegen einer eigenen Homepage
investieren. Suuuuuper Seite! Vielen
Dank!!!
Hallo, ich habe den Tip für diese
03.02.2002 info Seite von einem Kollegen
Hartmut
um 6 @ bekommen. Jetzt werde ich mir
Sailer
16:09:54 edv-sailer.de erstmal die gepackte Tutorial-Seite
mal zu Gemüte führen. Bis bald !
31.01.2002 schoenborn-boehm danke für diese super seite, hoffe,
a.schoenborn-
um 5 @ dass sie mir beim einstieg helfen
boehm
21:41:01 t-online.de wird.
Thank a lot for the WERY fine step
by step You have made. I have tryed
to locate some very interesting places
at the web, and your have be attched
to favorites. The starter kit STK500
22.01.2002 f.toft Mr. is very hard to get i Denmark but i
um 4 @ Flemming still think that this kit is the best
20:52:24 mail.dk Toft choice for a beginner (Atmel and
Assembler). If you have any
comments on that please feel free to
reply :-)) ...or if you have more
NEED to know for a beginner. Best
regards Flemming
Habe vor 1ner Woche angefangen
17.01.2002 Leslie.Belter
mit Assembler und muß sagen, das
um 3 @ Leslie
die Seite hier echt spitze ist weiter
12:28:43 Lift24.de
so ....:-)
Hello, Thank you very much for your
assembler-course. It helps me
04.01.2002 edmond.cambier
enormous. I will be the first buyer if
um 2 @ Edmond
you ever make a printed book of this
19:29:15 skynet.be
course. Herzlichen dank und fiele
gruesse von Edmond.
Thanks for the excellent web site! I
have wanted to try using the Atmel
chips for awhile now, but did not
03.01.2002 prooney797 know where to start. Your tutorial is
um 1 @ Paul just what I needed to give me a
04:55:49 aol.com kickstart. Thank you for the time and
energy you have put into the site to
share with others. Sincerely, Paul
Rooney Rochester, NY USA
©2007 by info at avr-asm-tutorial.net

http://www.avr-asm-tutorial.net/gb_new.html (2 of 2)1/20/2009 8:01:52 PM


WeblogOverview statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Overview statistic

Overview statistic for http://www.avr-asm-


tutorial.net
For more detailed informations follow these links:

● detailed overview by years,


● detailed overview by monthes,
● detailed overview by weeks.

Overview by year(s)

Year Files kBytes Visits


2009 0 0 0
2008 4,619,528 47,488,565 427,238
2007 4,653,101 46,321,840 447,483
2006 4,257,036 54,911,375 448,295
2005 3,584,636 76,835,133 209,597
2004 1,958,772 56,749,473 233,430
2003 1,547,301 25,108,490 183,108
2002 983,795 14,718,534 115,603
2001 38,127 622,757 4,345

Overview by monthes

Year Month Files kBytes Visits


2009 01 250,249 2,890,289 21,601
2008 12 389,361 4,234,362 35,134
2008 11 397,976 4,112,682 35,950
2008 10 388,072 3,970,505 34,670
2008 09 338,728 3,506,122 30,942
2008 08 325,431 3,325,247 29,984
2008 07 337,259 3,468,734 31,663
2008 06 360,891 3,507,461 34,174
2008 05 379,466 3,704,955 38,775
2008 04 407,495 4,098,867 41,262
2008 03 430,454 4,213,968 38,638
2008 02 421,013 4,423,773 36,663
2008 01 443,381 4,921,881 39,382
2007 12 389,188 4,163,349 35,733
2007 11 399,438 4,379,758 38,646
2007 10 393,108 4,158,616 35,982
2007 09 344,460 3,726,039 32,357
2007 08 356,200 3,615,385 37,422
2007 07 363,355 3,532,212 38,852
2007 06 360,710 3,412,690 41,753
2007 05 412,763 3,818,835 39,010
2007 04 378,213 3,480,950 34,922
2007 03 432,750 3,864,605 38,800
2007 02 381,685 3,719,329 35,326
2007 01 441,219 4,449,422 38,679
2006 12 366,238 3,769,396 34,127
2006 11 411,115 4,266,796 36,015
2006 10 381,864 3,893,060 34,115
2006 09 344,765 3,603,196 31,078
2006 08 341,845 3,554,277 29,834
2006 07 306,655 3,111,051 29,506
2006 06 303,536 3,002,349 29,779
2006 05 352,300 3,246,425 33,269
2006 04 354,655 4,352,375 38,841
2006 03 387,769 8,135,243 48,453
2006 02 338,883 6,876,038 44,982
2006 01 367,411 7,101,169 58,296
2005 12 317,743 6,832,334 39,469
2005 11 324,802 6,715,522 39,891
2005 10 333,611 6,915,288 40,804
2005 09 299,169 6,312,823 39,231
2005 08 287,736 5,987,198 43,137
2005 07 269,664 5,734,125 33,175
2005 06 272,268 6,134,069 23,649
2005 05 305,161 6,590,450 26,709
2005 04 303,406 6,677,816 27,397
2005 03 309,149 6,914,067 28,381
2005 02 288,178 6,179,603 25,595
2005 01 273,749 5,841,838 24,540
2004 12 240,839 5,508,131 22,831
2004 11 250,058 5,754,223 22,235
2004 10 225,441 5,220,793 21,193
2004 09 147,965 4,967,527 19,077
2004 08 129,076 4,195,975 17,377
2004 07 123,230 4,006,458 17,397
2004 06 130,812 4,194,096 17,411
2004 05 136,478 4,268,446 18,288
2004 04 138,334 4,366,760 19,212
2004 03 160,232 5,095,708 20,921
2004 02 142,017 4,639,135 19,063
2004 01 134,290 4,532,221 18,425
2003 12 129,929 3,351,620 16,201
2003 11 186,551 2,407,811 18,217
2003 10 147,187 2,187,215 17,761
2003 09 118,760 1,896,385 14,689
2003 08 104,791 1,810,596 12,543
2003 07 116,029 1,936,903 14,557
2003 06 110,556 1,780,294 14,101
2003 05 120,392 1,881,790 15,186
2003 04 126,246 1,999,966 15,153
2003 03 141,870 2,231,568 16,449
2003 02 127,673 1,940,079 14,492
2003 01 117,317 1,694,624 13,759
2002 12 102,512 1,531,767 12,216
2002 11 111,437 1,534,236 13,463
2002 10 114,906 1,475,649 13,976
2002 09 94,122 1,377,586 11,912
2002 08 81,267 1,145,515 10,101
2002 07 72,477 1,077,739 9,470
2002 06 77,046 1,180,832 9,235
2002 05 87,517 1,295,500 10,263
2002 04 61,880 1,096,159 6,017
2002 03 64,747 1,067,339 6,627
2002 02 61,971 1,044,924 6,542
2002 01 62,507 1,038,299 6,700
2001 12 38,121 622,751 4,344
2001 11 6 6 1

Overview by weeks

Year Week Files kBytes Visits


2009 03 103,699 1,190,911 9,002
2009 02 94,077 1,073,579 8,248
2009 01 52,473 625,799 4,351
2008 53 36,255 453,518 3,073
2008 52 79,584 837,592 6,978
2008 51 91,331 1,005,642 8,142
2008 50 87,534 930,188 8,266
2008 49 94,657 1,007,422 8,675
2008 48 91,390 947,417 8,213
2008 47 90,931 927,091 8,623
2008 46 94,684 990,274 8,402
2008 45 96,260 1,014,203 8,519
2008 44 93,193 950,788 8,492
2008 43 94,663 981,127 7,951
2008 42 87,477 854,496 7,797
2008 41 82,579 869,923 7,660
2008 40 78,795 802,384 7,264
2008 39 81,757 889,634 7,251
2008 38 83,142 918,990 7,380
2008 37 75,792 720,893 7,161
2008 36 74,113 722,089 6,849
2008 35 77,350 794,359 7,078
2008 34 74,675 788,059 6,945
2008 33 72,476 728,486 6,794
2008 32 73,479 728,215 6,643
2008 31 70,124 736,087 6,307
2008 30 76,003 793,538 6,834
2008 29 74,653 778,960 6,970
2008 28 79,691 836,413 7,615
2008 27 75,903 729,440 7,638
2008 26 82,023 797,715 7,836
2008 25 84,241 826,079 7,864
2008 24 84,361 819,719 8,202
2008 23 84,796 802,182 8,011
2008 22 86,563 804,572 8,422
2008 21 90,919 914,579 8,968
2008 20 85,107 868,345 8,991
2008 19 84,797 824,561 9,048
2008 18 86,341 839,531 8,745
2008 17 90,797 917,777 9,302
2008 16 93,491 894,348 9,467
2008 15 97,791 950,895 9,757
2008 14 98,182 1,046,294 9,697
2008 13 95,595 915,301 8,953
2008 12 95,105 955,920 8,334
2008 11 98,278 955,671 8,786
2008 10 100,424 1,007,929 8,953
2008 09 100,602 970,317 8,978
2008 08 100,864 996,243 9,079
2008 07 98,471 993,947 8,762
2008 06 108,381 1,301,350 8,644
2008 05 100,723 1,038,026 9,006
2008 04 103,769 1,089,871 9,342
2008 03 106,526 1,301,950 9,083
2008 02 97,619 1,064,549 8,837
2008 01 75,270 853,658 6,650
2007 53 11,416 125,262 1,028
2007 52 78,968 871,029 7,063
2007 51 85,899 896,862 7,782
2007 50 92,665 989,861 8,845
2007 49 96,138 1,019,173 8,771
2007 48 91,529 945,837 8,985
2007 47 98,324 1,124,539 10,573
2007 46 93,683 1,085,276 8,656
2007 45 90,189 980,549 8,223
2007 44 92,593 952,580 8,249
2007 43 93,558 1,047,512 8,309
2007 42 83,092 860,732 7,764
2007 41 89,955 1,013,775 8,130
2007 40 83,725 788,736 7,983
2007 39 83,052 940,741 7,808
2007 38 83,678 864,869 7,789
2007 37 81,068 883,684 7,735
2007 36 76,668 817,528 7,158
2007 35 82,792 888,790 7,720
2007 34 79,749 810,959 8,039
2007 33 81,949 789,997 8,287
2007 32 77,269 806,456 9,023
2007 31 82,385 787,287 8,785
2007 30 82,099 797,249 8,580
2007 29 78,549 762,327 8,477
2007 28 84,147 888,283 9,040
2007 27 80,976 746,645 9,117
2007 26 82,024 781,048 9,275
2007 25 86,711 768,544 9,808
2007 24 84,461 858,335 10,080
2007 23 85,918 783,905 10,299
2007 22 88,843 858,914 8,903
2007 21 93,665 891,756 8,654
2007 20 89,684 839,880 8,420
2007 19 96,530 901,667 9,095
2007 18 88,053 751,097 8,334
2007 17 92,660 854,293 8,494
2007 16 88,497 757,780 8,815
2007 15 87,063 859,506 8,119
2007 14 86,908 799,142 7,584
2007 13 91,478 824,561 8,152
2007 12 97,957 881,537 8,831
2007 11 101,185 891,230 9,380
2007 10 95,946 877,896 8,769
2007 09 104,478 960,212 8,603
2007 08 90,033 882,391 8,772
2007 07 97,321 998,072 8,592
2007 06 91,225 825,883 8,768
2007 05 100,191 1,015,791 9,355
2007 04 105,705 1,020,383 9,199
2007 03 102,174 1,015,423 8,830
2007 02 100,378 1,069,247 8,596
2007 01 87,898 866,809 7,837
2006 52 74,139 741,927 6,740
2006 51 79,708 817,243 7,618
2006 50 84,167 864,926 8,153
2006 49 93,153 988,486 8,402
2006 48 90,544 907,143 8,097
2006 47 96,599 968,798 8,577
2006 46 102,745 1,160,311 8,571
2006 45 93,103 941,974 8,352
2006 44 90,850 921,810 8,038
2006 43 85,361 931,280 7,813
2006 42 89,380 869,692 7,508
2006 41 84,149 847,602 7,410
2006 40 85,201 871,251 8,002
2006 39 87,765 981,617 7,864
2006 38 76,961 771,506 7,188
2006 37 82,190 846,005 7,405
2006 36 74,377 752,366 6,800
2006 35 84,900 970,132 7,111
2006 34 82,370 843,781 7,316
2006 33 73,379 732,752 6,550
2006 32 74,508 758,363 6,445
2006 31 70,736 696,396 6,165
2006 30 71,068 714,309 6,075
2006 29 71,893 717,791 6,869
2006 28 67,240 683,728 7,001
2006 27 70,020 742,812 6,907
2006 26 70,744 721,073 7,295
2006 25 73,253 757,016 7,289
2006 24 66,156 654,134 6,734
2006 23 67,494 605,307 6,563
2006 22 78,332 786,689 6,981
2006 21 77,646 761,304 7,030
2006 20 81,515 734,268 7,676
2006 19 82,461 755,648 7,671
2006 18 74,211 627,110 7,507
2006 17 83,151 770,288 7,977
2006 16 78,963 701,865 7,887
2006 15 83,694 606,505 10,532
2006 14 87,656 1,870,237 9,921
2006 13 84,053 1,773,654 10,886
2006 12 90,291 1,796,652 10,947
2006 11 88,853 1,959,905 10,696
2006 10 85,998 1,758,462 10,994
2006 09 84,323 1,707,952 10,442
2006 08 84,703 1,833,880 10,573
2006 07 87,040 1,772,226 11,389
2006 06 84,089 1,645,047 11,829
2006 05 85,640 1,712,830 11,630
2006 04 82,522 1,624,817 13,961
2006 03 86,709 1,528,690 14,626
2006 02 87,248 1,686,112 13,484
2006 01 76,313 1,582,493 11,065
2006 00 7,472 133,210 1,733
2005 51 66,030 1,380,423 8,210
2005 50 72,846 1,553,747 9,292
2005 49 76,015 1,693,229 9,270
2005 48 83,234 1,837,478 10,305
2005 47 77,382 1,589,331 9,365
2005 46 74,094 1,555,786 8,844
2005 45 72,917 1,490,502 8,896
2005 44 73,000 1,432,276 9,065
2005 43 72,281 1,559,238 8,540
2005 42 79,181 1,699,477 10,459
2005 41 78,960 1,553,047 10,118
2005 40 73,419 1,538,205 8,052
2005 39 74,561 1,504,918 8,615
2005 38 70,491 1,477,483 8,957
2005 37 76,962 1,640,191 12,342
2005 36 62,016 1,340,445 7,258
2005 35 60,083 1,305,730 7,935
2005 34 63,570 1,367,785 8,693
2005 33 63,731 1,272,836 10,083
2005 32 63,654 1,263,100 10,206
2005 31 69,347 1,461,062 10,554
2005 30 66,098 1,402,035 10,152
2005 29 62,052 1,242,051 6,392
2005 28 58,819 1,182,064 7,305
2005 27 61,290 1,453,923 7,475
2005 26 61,946 1,539,925 5,249
2005 25 57,648 1,244,187 5,118
2005 24 63,351 1,440,493 5,507
2005 23 65,119 1,404,280 5,566
2005 22 65,729 1,351,576 5,868
2005 21 63,997 1,339,772 5,618
2005 20 65,516 1,419,368 6,073
2005 19 76,710 1,602,285 6,279
2005 18 71,374 1,676,382 6,297
2005 17 69,369 1,511,724 6,319
2005 16 71,978 1,634,201 6,705
2005 15 72,235 1,604,032 6,416
2005 14 72,914 1,587,479 6,516
2005 13 63,914 1,464,157 5,595
2005 12 60,806 1,284,915 5,882
2005 11 71,465 1,680,715 6,636
2005 10 76,049 1,584,181 6,713
2005 09 70,506 1,598,749 6,511
2005 08 71,614 1,572,621 6,518
2005 07 73,373 1,585,671 6,550
2005 06 77,156 1,608,802 6,299
2005 05 68,146 1,482,965 6,392
2005 04 71,421 1,502,945 6,200
2005 03 70,234 1,536,689 6,242
2005 02 64,339 1,337,002 5,859
2005 01 56,407 1,196,779 5,194
2004 53 50,048 1,159,078 4,289
2004 52 49,888 1,169,666 4,650
2004 51 56,304 1,263,334 5,397
2004 50 57,163 1,250,815 5,710
2004 49 60,168 1,403,128 5,634
2004 48 59,435 1,395,834 5,523
2004 47 59,341 1,367,594 5,141
2004 46 55,406 1,257,235 4,971
2004 45 55,840 1,265,690 4,831
2004 44 57,206 1,164,913 5,022
2004 43 51,420 1,086,280 4,641
2004 42 57,926 1,252,992 5,086
2004 41 47,176 1,276,382 4,854
2004 40 31,381 1,108,896 4,499
2004 39 35,281 1,210,097 4,731
2004 38 33,332 1,092,950 4,439
2004 37 35,799 1,235,492 4,310
2004 36 32,649 1,085,370 3,931
2004 35 32,118 1,069,484 4,221
2004 34 30,470 954,381 4,104
2004 33 30,208 929,148 3,760
2004 32 25,205 848,842 3,666
2004 31 26,147 862,707 3,814
2004 30 27,097 907,861 4,175
2004 29 26,985 873,805 3,692
2004 28 29,632 908,359 4,005
2004 27 30,020 1,001,513 4,015
2004 26 30,355 1,014,982 4,066
2004 25 30,269 984,462 4,126
2004 24 29,169 912,188 4,003
2004 23 30,732 926,816 3,836
2004 22 31,414 1,012,877 4,149
2004 21 29,597 876,820 3,825
2004 20 31,766 1,024,934 4,405
2004 19 31,991 1,018,253 4,336
2004 18 31,940 1,046,854 4,443
2004 17 32,267 1,093,715 4,387
2004 16 33,037 989,543 4,441
2004 15 30,908 889,200 4,378
2004 14 34,776 1,095,950 4,831
2004 13 36,864 1,157,202 4,662
2004 12 35,089 1,084,964 4,701
2004 11 33,912 1,075,311 4,601
2004 10 37,430 1,242,220 4,721
2004 09 37,362 1,212,527 4,881
2004 08 36,782 1,171,722 4,689
2004 07 31,926 1,079,494 4,508
2004 06 31,795 1,055,695 4,477
2004 05 33,064 1,125,687 4,349
2004 04 30,469 1,031,955 4,103
2004 03 31,191 1,073,858 4,297
2004 02 31,105 1,033,713 4,289
2004 01 23,174 658,299 3,286
2003 52 22,944 563,135 3,001
2003 51 26,812 713,912 3,676
2003 50 33,706 856,563 4,138
2003 49 35,798 945,282 3,995
2003 48 33,168 533,019 4,238
2003 47 33,622 637,696 4,452
2003 46 64,402 504,136 4,189
2003 45 46,629 583,928 4,310
2003 44 45,997 565,215 4,253
2003 43 33,837 558,779 4,080
2003 42 30,189 473,149 4,069
2003 41 27,788 451,589 3,953
2003 40 27,118 415,506 3,575
2003 39 22,009 341,804 2,943
2003 38 28,952 509,431 3,721
2003 37 33,638 519,665 3,690
2003 36 25,149 397,507 3,194
2003 35 27,392 525,479 2,998
2003 34 23,890 368,758 2,752
2003 33 22,043 467,999 2,843
2003 32 24,573 335,856 2,912
2003 31 21,964 376,773 2,987
2003 30 26,773 455,988 3,257
2003 29 23,960 420,751 3,189
2003 28 27,529 457,726 3,265
2003 27 26,974 417,110 3,404
2003 26 24,655 394,731 3,341
2003 25 27,745 457,958 3,478
2003 24 26,328 400,542 3,155
2003 23 24,133 396,034 3,227
2003 22 27,809 458,118 3,397
2003 21 26,891 458,975 3,279
2003 20 28,098 423,991 3,774
2003 19 28,516 427,046 3,477
2003 18 26,020 410,753 3,261
2003 17 30,368 433,554 3,517
2003 16 23,874 378,530 3,237
2003 15 34,115 571,900 3,761
2003 14 28,589 429,705 3,606
2003 13 28,290 424,202 3,453
2003 12 28,144 446,868 3,489
2003 11 35,103 607,803 3,868
2003 10 37,525 577,065 4,171
2003 09 35,129 525,480 3,917
2003 08 36,166 578,849 3,825
2003 07 31,795 454,086 3,535
2003 06 28,556 423,172 3,602
2003 05 26,057 350,563 3,096
2003 04 27,393 411,573 3,138
2003 03 26,486 377,879 3,332
2003 02 26,978 382,026 2,966
2003 01 19,760 314,857 2,379
2002 52 21,523 325,084 2,436
2002 51 24,492 402,894 2,785
2002 50 25,663 360,435 2,928
2002 49 23,430 339,139 3,096
2002 48 23,097 350,835 2,906
2002 47 26,899 393,478 3,142
2002 46 26,150 349,279 3,250
2002 45 27,692 353,554 3,357
2002 44 26,173 313,582 3,060
2002 43 28,664 369,661 3,275
2002 42 26,270 342,586 3,188
2002 41 26,325 330,344 3,127
2002 40 21,869 315,757 2,937
2002 39 25,176 409,211 3,114
2002 38 21,397 322,889 2,902
2002 37 20,500 255,245 2,662
2002 36 20,318 280,242 2,491
2002 35 20,471 259,850 2,597
2002 34 16,089 227,395 2,007
2002 33 16,885 220,022 2,057
2002 32 18,330 277,797 2,166
2002 31 19,101 294,817 2,518
2002 30 18,509 299,494 2,256
2002 29 15,050 207,840 2,016
2002 28 14,993 223,063 2,033
2002 27 16,908 251,119 2,184
2002 26 17,010 252,822 2,100
2002 25 16,453 264,274 2,014
2002 24 19,260 310,569 2,216
2002 23 20,004 299,010 2,354
2002 22 18,902 299,649 2,365
2002 21 17,916 276,702 2,064
2002 20 17,035 236,541 2,181
2002 19 23,946 306,207 2,421
2002 18 19,236 306,491 2,370
2002 17 15,398 266,872 1,418
2002 16 12,479 221,800 1,204
2002 15 14,640 272,732 1,396
2002 14 14,164 258,822 1,412
2002 13 12,906 193,170 1,273
2002 12 12,914 218,286 1,445
2002 11 14,986 257,725 1,496
2002 10 15,687 245,178 1,715
2002 09 16,173 299,599 1,628
2002 08 14,556 233,087 1,533
2002 07 16,245 284,520 1,750
2002 06 16,859 283,165 1,726
2002 05 19,431 287,917 1,737
2002 04 15,679 275,548 1,640
2002 03 12,101 212,195 1,418
2002 02 13,096 213,244 1,593
2002 01 10,080 167,668 1,108
2001 52 9,474 156,432 963
2001 51 11,133 224,898 1,104
2001 50 8,413 115,022 1,072
2001 49 7,521 104,920 1,001
2001 48 100 749 14
To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/index.html1/20/2009 8:02:04 PM
Weblog for http://www.avr-asm-tutorial.net

Path: Home ==> Statistic Overview ==> Overview by year(s)

Overview by year(s) forhttp://www.avr-asm-


tutorial.net
For more detailed informations follow these links:

● Overview by year(s),

Year Link to detailed information


2009 host names, sorted bydifferent criteria
To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/years.html1/20/2009 8:02:09 PM
Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2009y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2009

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 11715 IPs and host names , sorted by number of files

N IPs and host names times %


1 41.201.123.244=(not found) 1,280 0.61
2 78.96.155.157=(not found) 1,113 0.53
3 91.205.124.9=(not found) 1,026 0.49
85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.
4 874 0.42
de
5 67.195.37.111=llf320022.crawl.yahoo.net 749 0.36
6 72.30.87.112=llf531192.crawl.yahoo.net 708 0.34
7 85.9.121.249=(not found) 704 0.34
8 90.149.187.3=149-187-3.oke2-bras5.adsl.tele2.no 643 0.31
9 66.249.71.207=crawl-66-249-71-207.googlebot.com 610 0.29
10 66.249.71.205=crawl-66-249-71-205.googlebot.com 608 0.29
11 66.249.71.206=crawl-66-249-71-206.googlebot.com 589 0.28
12 78.46.86.53=crawl1.hetzner.itroot.de 423 0.20
13 67.195.37.164=llf320062.crawl.yahoo.net 395 0.19
14 84.161.234.174=p54A1EAAE.dip.t-dialin.net 390 0.19
15 80.191.119.218=(not found) 378 0.18
16 210.212.169.118=(not found) 377 0.18
17 84.146.240.138=p5492F08A.dip.t-dialin.net 375 0.18
18 217.85.203.141=pD955CB8D.dip.t-dialin.net 354 0.17
19 208.115.111.244=crawl3.dotnetdotcom.org 351 0.17
20 72.30.65.32=llf531371.crawl.yahoo.net 328 0.16
21 79.193.117.235=p4FC175EB.dip.t-dialin.net 327 0.16
22 91.180.109.162=162.109-180-91.adsl-dyn.isp.belgacom.be 325 0.15
23 64.88.164.198=(not found) 304 0.14
24 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 300 0.14
25 92.75.230.63=dslb-092-075-230-063.pools.arcor-ip.net 299 0.14
Sum 209,710 100.00

To top of page

Top 25 of 11715 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.205.124.9=(not found) 33,688 1.37
85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.
2 31,904 1.30
de
3 78.96.155.157=(not found) 25,173 1.03
4 41.201.123.244=(not found) 19,455 0.79
5 72.30.87.112=llf531192.crawl.yahoo.net 19,341 0.79
6 89.61.194.44=Zc22c.z.pppool.de 12,313 0.50
7 91.22.201.213=p5B16C9D5.dip.t-dialin.net 10,417 0.42
8 84.166.54.47=p54A6362F.dip0.t-ipconnect.de 10,057 0.41
9 85.9.121.249=(not found) 9,742 0.40
10 77.22.115.197=(not found) 9,674 0.39
11 67.195.37.111=llf320022.crawl.yahoo.net 9,634 0.39
12 84.161.234.174=p54A1EAAE.dip.t-dialin.net 9,287 0.38
13 84.146.240.138=p5492F08A.dip.t-dialin.net 8,416 0.34
14 72.30.65.32=llf531371.crawl.yahoo.net 8,410 0.34
15 217.85.203.141=pD955CB8D.dip.t-dialin.net 8,088 0.33
16 87.123.221.130=i577BDD82.versanet.de 8,000 0.33
17 80.142.240.222=p508EF0DE.dip.t-dialin.net 7,757 0.32
18 87.152.175.189=p5798AFBD.dip.t-dialin.net 7,289 0.30
19 141.52.232.84=webproxy.fzk.de 7,169 0.29
20 79.193.117.235=p4FC175EB.dip.t-dialin.net 6,735 0.27
21 67.195.37.164=llf320062.crawl.yahoo.net 6,729 0.27
22 82.82.209.105=dslc-082-082-209-105.pools.arcor-ip.net 6,619 0.27
23 91.12.114.10=p5B0C720A.dip.t-dialin.net 6,218 0.25
24 84.132.241.112=p5484F170.dip.t-dialin.net 6,138 0.25
25 85.127.135.21=85-127-135-21.dynamic.xdsl-line.inode.at 6,123 0.25
Sum 2,454,027 100.00

To top of page

Top 25 of 2052 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.207=crawl-66-249-71-207.googlebot.com 191 2.26
2 66.249.71.206=crawl-66-249-71-206.googlebot.com 191 2.26
3 66.249.71.205=crawl-66-249-71-205.googlebot.com 181 2.14
4 67.195.37.111=llf320022.crawl.yahoo.net 155 1.83
5 72.30.87.112=llf531192.crawl.yahoo.net 131 1.55
6 67.195.37.164=llf320062.crawl.yahoo.net 94 1.11
7 58.148.8.37=(not found) 90 1.06
8 81.52.143.16=natcrawlbloc03.net.m1.fti.net 68 0.80
9 193.252.149.15=natcrawlbloc02.net.s1.fti.net 67 0.79
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 65 0.77
11 212.143.177.197=(not found) 65 0.77
12 88.131.106.16=(not found) 57 0.67
13 81.52.143.26=natcrawlbloc05.net.m1.fti.net 54 0.64
14 72.30.65.32=llf531371.crawl.yahoo.net 50 0.59
15 208.115.111.244=crawl3.dotnetdotcom.org 46 0.54
16 193.47.80.44=crawl08.exabot.com 46 0.54
17 84.247.45.83=(not found) 43 0.51
18 193.252.149.16=natcrawlbloc04.net.s1.fti.net 37 0.44
19 208.44.234.50=(not found) 36 0.43
20 67.195.37.157=llf320058.crawl.yahoo.net 35 0.41
21 203.209.252.66=hd901036.inktomisearch.com 33 0.39
22 66.235.124.3=crawler5003.ask.com 32 0.38
65.55.209.156=msnbot-65-55-209-156.search.msn.
23 31 0.37
com
24 91.67.186.89=91-67-186-89-dynip.superkabel.de 30 0.35
25 78.56.80.179=78-56-80-179.static.zebra.lt 29 0.34
Sum 8,460 100.00

To top of page

Top 25 of 112 countries of origin , sorted by number of files

N countries of origin times %


1 net 60,645 28.92
2 Germany 47,890 22.84
3 (unresolved) 38,365 18.29
4 com 12,017 5.73
5 Poland 6,537 3.12
6 Austria 5,111 2.44
7 Switzerland 3,442 1.64
8 Netherlands 2,765 1.32
9 India 2,017 0.96
10 Italy 2,011 0.96
11 Hungary 1,704 0.81
12 Indonesia 1,537 0.73
13 Czech Republic 1,420 0.68
14 Belgium 1,410 0.67
15 Greece 1,254 0.60
16 Lithuania 1,234 0.59
17 Brazil 1,124 0.54
18 Romania 1,074 0.51
19 Sweden 1,067 0.51
20 Canada 1,055 0.50
21 Slovak Republic 1,015 0.48
22 Australia 969 0.46
23 Norway 962 0.46
24 Russian Federation 951 0.45
25 edu 815 0.39
Sum 209,710 100.00

To top of page

Top 25 of 187 pathes , sorted by number of files

N pathes times %
1 /common/ 72,219 34.44
2 /avr_gra/ 39,965 19.06
3 / 24,058 11.47
4 /avr_en/beginner/ 8,166 3.89
5 /avr_de/beginner/ 6,716 3.20
6 /avr_de/ 6,191 2.95
7 /avr_en/ 5,804 2.77
8 /avr_de/rechnen/ 3,865 1.84
9 /avr_de/fcount/ 3,526 1.68
10 /avr_en/calc/ 3,391 1.62
11 /avr_de/stepper/ 2,756 1.31
12 /avr_de/praesentation/ 2,628 1.25
13 /avr_de/quellen/ 2,017 0.96
14 /avr_en/source/ 1,946 0.93
15 /avr_en/keypad/ 1,758 0.84
16 /avr_de/keypad/ 1,641 0.78
/avr_de/rechteckgen/
17 1,599 0.76
bilder/
18 /gavrasm/ 1,553 0.74
19 /avr_en/signalgen/pics/ 1,549 0.74
20 /avr_de/zeitschleifen/ 1,295 0.62
21 /avr_en/stepper/ 1,225 0.58
22 /avr_de/interrupts/ 1,212 0.58
23 /akkuload/ 822 0.39
24 /avr_en/fcount/ 763 0.36
25 /gavrasm/v22/ 751 0.36
Sum 209,710 100.00

To top of page

Top 25 of 187 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 457,267 18.63
2 /avr_gra/ 416,310 16.96
3 /avr_de/intro/pdf/ 204,746 8.34
4 / 139,915 5.70
5 /avr_de/fcount/ 134,348 5.47
6 /avr_de/ 103,512 4.22
7 /avr_en/ 83,912 3.42
8 /gavrasm/v22/ 81,004 3.30
9 /avr_de/stepper/ 74,614 3.04
10 /avr_en/beginner/ 69,144 2.82
11 /avr_de/beginner/ 66,098 2.69
12 /avr_en/signalgen/pics/ 40,854 1.66
/avr_de/rechteckgen/
13 40,555 1.65
bilder/
14 /avr_de/intro/ppt/ 38,280 1.56
15 /avr_de/rechnen/ 35,488 1.45
16 /common/ 34,632 1.41
17 /avr_en/calc/ 30,809 1.26
18 /privat/magloop/ 30,605 1.25
19 /avr_en/stepper/ 30,478 1.24
20 /avr_en/fcount/ 30,435 1.24
21 /avr_en/signalgen/ 27,159 1.11
22 /avr_de/rechteckgen/ 22,596 0.92
23 /akkuload/ 20,937 0.85
24 /avr_de/interrupts/ 13,618 0.55
25 /avr_en/keypad/ 13,500 0.55
Sum 2,454,027 100.00

To top of page

Top 25 of 2049 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 10,717 5.11
2 /avr_gra/RingLogo.jpg 5,649 2.69
3 /common/app.gif 4,667 2.23
/common/knowhow.
4 4,661 2.22
gif
5 /common/akkuload.gif 4,657 2.22
/common/download.
6 4,654 2.22
gif
7 /common/clock.gif 4,640 2.21
8 /common/gavrasm.gif 4,635 2.21
9 /common/adc.gif 4,628 2.21
/common/gavrasmw.
10 4,626 2.21
gif
11 /common/example.gif 4,623 2.20
12 /common/calc.gif 4,623 2.20
13 /common/hardware.gif 4,619 2.20
14 /common/r2r.gif 4,619 2.20
15 /common/keyb.gif 4,615 2.20
16 /common/beginner.gif 4,609 2.20
17 /avr_gra/stk_lcd.jpg 4,608 2.20
18 /index.html 3,357 1.60
19 /avr_de/index.html 2,757 1.31
20 /avr_en/index.html 2,664 1.27
21 /avr_2313.gif 2,577 1.23
22 /dg4fac.gif 2,567 1.22
23 /avr-asm-tutorial.gif 2,566 1.22
24 /common/ints.gif 2,452 1.17
25 /common/delay.gif 2,448 1.17
Sum 209,710 100.00

To top of page

Top 25 of 2049 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 150,335 6.13
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 107,298 4.37
3 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 69,820 2.85
4 /avr_de/index.html 65,656 2.68
5 /avr_en/index.html 55,995 2.28
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 48,452 1.97
pdf
7 /avr_2313.gif 46,236 1.88
8 /avr_gra/tn13_exp.jpg 43,564 1.78
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 41,964 1.71
10 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 40,025 1.63
11 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 37,954 1.55
12 /dg4fac.gif 27,579 1.12
13 /avr_de/fcount/dscf0004.jpg 26,169 1.07
14 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 25,392 1.03
15 /avr_gra/r2r_hardware.jpg 23,977 0.98
16 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 23,485 0.96
17 /avr_de/fcount/dscf0005.jpg 23,008 0.94
18 /avr_gra/pwm_simul.jpg 22,558 0.92
19 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 22,268 0.91
20 /avr_de/fcount/dscf0001.jpg 21,691 0.88
21 /favicon.ico 21,037 0.86
22 /avr_de/intro/pdf/Teil1_Prozessor.pdf 20,493 0.84
23 /avr_gra/tn13_exp.gif 19,798 0.81
24 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 18,702 0.76
25 /avr_en/signalgen/pics/rectgen_wiring.jpg 18,697 0.76
Sum 2,454,027 100.00

To top of page

Top 25 of 510 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 3,357 7.83
2 /avr_de/index.html 2,757 6.43
3 /avr_en/index.html 2,664 6.22
4 /avr_en/beginner/LEFT.html 1,617 3.77
5 /avr_en/beginner/index.html 1,337 3.12
6 /avr_en/beginner/RIGHT.html 1,304 3.04
7 /avr_de/beginner/index.html 1,051 2.45
8 /avr_de/beginner/links.html 1,031 2.41
9 /avr_de/beginner/rechts.html 972 2.27
/avr_en/beginner/HARDWARE.
10 596 1.39
html
11 /avr_de/beginner/hardware.html 502 1.17
12 /avr_en/beginner/REGISTER.html 480 1.12
13 /avr_en/AVR_DAC.html 470 1.10
14 /avr_de/stepper/stepper.html 387 0.90
15 /avr_de/beginner/register.html 385 0.90
16 /avr_en/keypad/keyboard.html 384 0.90
17 /avr_en/beginner/JUMP.html 381 0.89
18 /avr_de/beginner/sprung.html 367 0.86
19 /avr_de/praesentation/index.html 365 0.85
20 /avr_de/apps.html 353 0.82
21 /avr_de/keypad/keyboard.html 352 0.82
22 /avr_en/beginner/PORTS.html 341 0.80
23 /avr_de/avr_tut.html 321 0.75
24 /avr_de/fcount/fcount_m8.html 319 0.74
25 /avr_de/beginner/ports.html 311 0.73
Sum 42,851 100.00

To top of page

Top 25 of 510 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 65,656 13.18
2 /avr_en/index.html 55,995 11.24
3 /index.html 17,880 3.59
4 /avr_de/dcf77uhr.html 11,246 2.26
5 /gb_new.html 10,400 2.09
6 /avr_de/beginner/sprung.html 9,879 1.98
7 /avr_en/beginner/RIGHT.html 9,460 1.90
8 /avr_en/beginner/JUMP.html 9,386 1.88
9 /avr_en/keypad/keyboard.html 7,961 1.60
10 /avr_de/keypad/keyboard.html 7,150 1.44
11 /avr_en/beginner/CALC.html 7,072 1.42
12 /avr_de/beginner/rechnen.html 6,966 1.40
13 /avr_en/AVR_DAC.html 6,879 1.38
14 /avr_de/beginner/rechts.html 6,856 1.38
15 /avr_en/beginner/LEFT.html 6,052 1.21
16 /avr_de/stepper/stepper.html 5,872 1.18
17 /avr_en/beginner/REGISTER.html 5,800 1.16
18 /avr_de/beginner/pdetail.html 5,526 1.11
19 /sitemap_de.html 5,440 1.09
/avr_de/rechteckgen/rectgen_m8.
20 5,320 1.07
html
21 /avr_de/beginner/hardware.html 5,225 1.05
22 /avr_en/signalgen/rectgen_m8.html 5,170 1.04
23 /avr_de/beginner/commands.html 5,061 1.02
24 /avr_en/beginner/HARDWARE.html 5,031 1.01
/avr_en/beginner/COMMANDS.
25 5,016 1.01
html
Sum 498,162 100.00

To top of page

Top 25 of 757 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 5,649 17.57
2 /avr_gra/stk_lcd.jpg 4,608 14.33
3 /avr_gra/exp2313g.jpg 1,070 3.33
4 /avr_gra/8515.jpg 1,063 3.31
5 /avr_gra/tn13_exp.jpg 1,004 3.12
6 /avr_gra/avr_isp.jpg 1,000 3.11
7 /avr_gra/exp_2313.jpg 996 3.10
8 /avr_gra/r2r_wave.jpg 782 2.43
9 /avr_gra/r2r_sawtooth.jpg 711 2.21
10 /avr_gra/r2r_hardware.jpg 675 2.10
11 /avr_gra/r2r_triangle.jpg 666 2.07
12 /avr_gra/r2r_sawtoothupperbound.jpg 661 2.06
13 /avr_gra/r2r_sawtooth741.jpg 661 2.06
14 /avr_gra/r2r_upperbound.jpg 656 2.04
15 /avr_gra/AT90S8515.jpg 530 1.65
16 /avr_gra/apps.jpg 470 1.46
17 /avr_gra/pwm_simul.jpg 400 1.24
18 /avr_de/stepper/stepper_sm.jpg 397 1.23
19 /akkuload/dscf0030s.jpg 396 1.23
20 /avr_gra/adc8conn.jpg 393 1.22
21 /avr_de/stepper/supply.jpg 369 1.15
22 /avr_de/stepper/kp4m4-001.jpg 365 1.14
23 /avr_de/stepper/driver.jpg 363 1.13
24 /avr_de/praesentation/zuendtester.jpg 341 1.06
/avr_en/signalgen/pics/rectgen_280.
25 333 1.04
jpg
Sum 32,150 100.00

To top of page

Top 25 of 434 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 4,667 4.15
/common/knowhow.
2 4,661 4.14
gif
3 /common/akkuload.gif 4,657 4.14
/common/download.
4 4,653 4.13
gif
5 /common/clock.gif 4,640 4.12
6 /common/gavrasm.gif 4,635 4.12
7 /common/adc.gif 4,628 4.11
/common/gavrasmw.
8 4,626 4.11
gif
9 /common/example.gif 4,623 4.11
10 /common/calc.gif 4,623 4.11
11 /common/hardware.gif 4,619 4.10
12 /common/r2r.gif 4,619 4.10
13 /common/keyb.gif 4,615 4.10
14 /common/beginner.gif 4,609 4.10
15 /avr_2313.gif 2,577 2.29
16 /dg4fac.gif 2,567 2.28
17 /avr-asm-tutorial.gif 2,566 2.28
18 /common/ints.gif 2,452 2.18
19 /common/delay.gif 2,448 2.18
20 /common/tn13.gif 2,443 2.17
21 /avr_gra/2313.gif 2,225 1.98
22 /avr_gra/exp2313.gif 1,016 0.90
23 /avr_gra/avr_isp.gif 999 0.89
24 /avr_gra/isp6pin.gif 994 0.88
25 /avr_gra/tn13_exp.gif 993 0.88
Sum 112,533 100.00

To top of page

Top 25 of 193 entry pages , sorted by number of files

N entry pages times %


1 /index.html 1,618 17.72
2 /avr_en/index.html 937 10.26
3 /avr_de/index.html 775 8.49
4 /avr_en/beginner/index.html 408 4.47
5 /avr_en/AVR_DAC.html 276 3.02
6 /avr_de/beginner/index.html 239 2.62
7 /avr_de/stepper/stepper.html 212 2.32
8 /avr_en/beginner/HARDWARE.html 173 1.90
9 /avr_de/fcount/fcount_m8.html 155 1.70
10 /avr_de/avr_dac.html 153 1.68
11 /avr_de/beginner/hardware.html 146 1.60
12 /avr_en/keypad/keyboard.html 139 1.52
13 /avr_de/keypad/keyboard.html 139 1.52
14 /avr_en/signalgen/rectgen_m8.html 128 1.40
/avr_de/rechteckgen/rectgen_m8.
15 123 1.35
html
16 /avr_de/intro/index.html 122 1.34
17 /avr_en/AVR_ADC500.html 99 1.08
18 /avr_de/rechnen/konversion.html 95 1.04
19 /gb_new.html 92 1.01
20 /avr_de/rechnen/multiplikation.html 75 0.82
21 /avr_de/beginner/rechnen.html 75 0.82
22 /privat/stechlin/index.html 74 0.81
23 /avr_de/avr_adc500.html 72 0.79
24 /avr_en/beginner/REGISTER.html 71 0.78
25 /akkuload/de/index.html 69 0.76
Sum 9,129 100.00

To top of page

Top 25 of 300 cheat pages , sorted by number of files

N cheat pages times %


1 /index.html 1,026 8.76
2 /avr_en/index.html 895 7.64
3 /avr_de/index.html 781 6.67
4 /avr_en/AVR_DAC.html 346 2.95
5 274 2.34
6 /avr_en/beginner/HARDWARE.html 266 2.27
7 /avr_en/beginner/RIGHT.html 263 2.24
8 /avr_de/stepper/stepper.html 245 2.09
9 /avr_de/beginner/hardware.html 216 1.84
10 /avr_en/keypad/keyboard.html 213 1.82
11 /avr_de/keypad/keyboard.html 186 1.59
12 /avr_de/fcount/fcount_m8.html 179 1.53
13 /avr_de/avr_dac.html 177 1.51
14 /avr_de/beginner/rechts.html 169 1.44
15 /avr_en/beginner/REGISTER.html 153 1.31
16 /akkuload/de/index.html 139 1.19
/avr_de/rechteckgen/rectgen_m8.
17 135 1.15
html
18 /avr_en/AVR_ADC500.html 133 1.14
19 /avr_de/intro/index.html 120 1.02
20 /avr_de/praesentation/index.html 119 1.02
21 /avr_de/beginner/rechnen.html 119 1.02
22 /avr_de/beginner/sprung.html 118 1.01
23 /avr_en/signalgen/rectgen_m8.html 117 1.00
24 /avr_en/beginner/JUMP.html 116 0.99
25 /avr_en/beginner/SRAM.html 115 0.98
Sum 11,715 100.00

To top of page

Top 25 of 194 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 3,402 15.48
2 /avr_en/beginner/index.html 2,638 12.01
3 /avr_de/beginner/index.html 1,740 7.92
4 / 1,590 7.24
5 /avr_en/index.html 1,417 6.45
6 /avr_en/beginner/RIGHT.html 1,131 5.15
7 /avr_de/beginner/rechts.html 1,025 4.67
8 /avr_en/ 1,022 4.65
9 /avr_en/beginner/LEFT.html 890 4.05
10 /sitemap_de.html 662 3.01
11 /avr_de/beginner/links.html 599 2.73
12 /sitemap_en.html 476 2.17
13 /index.html 391 1.78
14 /avr_de/apps.html 356 1.62
15 /avr_de/interrupts/index.html 331 1.51
16 /avr_de/avr_tut.html 277 1.26
17 /avr_de/zeitschleifen/index.html 254 1.16
18 /avr_de/ 227 1.03
19 /avr_en/calc/index.html 202 0.92
20 /avr_en/AVR_TUT.html 188 0.86
21 /avr_en/APPS.html 170 0.77
/avr_en/signalgen/rectgen_m8.
22 133 0.61
html
23 /avr_de/rechnen/index.html 131 0.60
24 /avr_de/beginner/commands.html 119 0.54
25 /weblox_de/index.html 118 0.54
Sum 21,971 100.00

To top of page

Top 25 of 703 external referrers , sorted by number of files

N external referrers times %


1 - 10,955 82.20
2 http://www.webring.com/hub?ring=avr 87 0.65
3 http://www.mikrocontroller.net/articles/AVR 86 0.65
4 http://www.elektroda.pl/rtvforum/viewtopic.php?t=1191671 79 0.59
5 http://www.dg4fac.de/linksunten.html 60 0.45
6 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 46 0.35
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 42 0.32
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
8 39 0.29
kurs.htm
9 http://de.wikipedia.org/wiki/R2R-Netzwerk 37 0.28
10 http://www.serasidis.gr/link.htm 33 0.25
11 http://www.dg4fac.de/rechtsunten.html 32 0.24
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
12 32 0.24
ESC_by1_bz0_bs0.html
13 http://www.mikrocontroller.net/articles/Linksammlung 31 0.23
14 http://avr-asm.tripod.com/ 29 0.22
15 http://www.rowalt.de/mc/avr/linksd.htm 25 0.19
http://www.avrfreaks.net/index.php?
16 name=PNphpBB2&file=viewtopic&t=7067 25 0.19
3
17 http://www.educypedia.be/electronics/avr.htm 22 0.17
18 http://www.raw.to/rubriken/private_elektronik.html 22 0.17
19 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 21 0.16
20 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 21 0.16
21 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 21 0.16
22 http://www.dg4fac.de/stechlin/index.html 18 0.14
23 http://blackstrom.derschwarz.de/avr/avr/index.shtml 16 0.12
http://www.stud.uni-stuttgart.de/studweb/users/etk/etk39219/avrc/index
24 15 0.11
.htm
25 http://www.mikrocontroller.net/topic/10424 15 0.11
Sum 13,327 100.00

To top of page

Top 25 of 151 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 3,173 45.15
2 http://www.google.com 1,127 16.04
3 http://www.google.at 264 3.76
4 http://www.google.co.in 210 2.99
5 http://www.google.nl 149 2.12
6 http://www.google.pl 144 2.05
7 http://www.google.ch 138 1.96
8 http://www.google.co.uk 110 1.57
9 http://www.google.ca 98 1.39
10 http://www.google.ro 86 1.22
11 http://www.google.se 72 1.02
http://www.google.com.
12 68 0.97
au
13 http://www.google.co.id 57 0.81
14 http://www.google.be 55 0.78
15 http://search.yahoo.com 50 0.71
16 http://www.google.com.tr 45 0.64
http://de.search.yahoo.
17 45 0.64
com
18 http://www.google.fi 44 0.63
19 http://www.google.gr 42 0.60
20 http://www.google.it 42 0.60
http://www.google.com.
21 41 0.58
vn
22 http://www.google.es 41 0.58
23 http://www.google.hu 40 0.57
24 http://www.google.sk 39 0.55
25 http://www.google.fr 39 0.55
Sum 7,028 100.00

To top of page

Top 25 of 4310 search strings , sorted by number of files

N search strings times %


1 avr tutorial 192 2.73
2 avr assembler 139 1.98
3 avr 114 1.62
4 attiny13 70 1.00
5 assembler 65 0.92
6 avr programming 59 0.84
7 avr asm 40 0.57
assembler
8 40 0.57
commands
9 avr assembly 39 0.55
10 assembler tutorial 36 0.51
11 AVR tutorial 31 0.44
12 ATtiny13 29 0.41
13 avr asm tutorial 28 0.40
avr assembler
14 28 0.40
tutorial
15 atmel avr 27 0.38
16 AVR 26 0.37
17 atmega8 24 0.34
18 stk500 21 0.30
19 gavrasm 21 0.30
20 avr codes 21 0.30
21 avr assembly tutorial 20 0.28
22 atmel assembler 19 0.27
23 assembler lernen 16 0.23
24 Assembler 15 0.21
25 AVR Assembler 15 0.21
Sum 7,028 100.00

To top of page

Top 10 of 10 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 187,742 89.52
2 304 Not changed 19,807 9.44
3 206 Partial information 1,182 0.56
4 301 Permanently moved 497 0.24
5 404 File not found 370 0.18
6 405 Method not allowed 51 0.02

http://www.avr-asm-tutorial.net/weblox_en/2009y.html (1 of 2)1/20/2009 8:02:24 PM


Weblog statistic for http://www.avr-asm-tutorial.net

7 403 Forbidden 34 0.02


8 300 Multiple choices 17 0.01
9 xxx Unknown error 7 0.00
10 xxx Unknown error 3 0.00
Sum 209,710 100.00

To top of page

Top 25 of 128 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 116 31.35
2 /beginner_de.pdf 42 11.35
3 /avr_de/intro/ppt/beispiel10_snd.wav 14 3.78
4 /avr_de/interrupts/undefined 10 2.70
/_vti_bin/owssvr.dll?
5 9 2.43
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 9 2.43
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
7 /fcount/fcount_m8.html 8 2.16
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
8 20la 6 1.62
nguage_files/LEFT.htm
9 /hostnamehttp://www.poliauto.ca//media/test.txt?? 6 1.62
10 /keypad/gb_new.html 5 1.35
11 /avr_de/keypad/gb_new.html 4 1.08
12 /_vti_inf.html 4 1.08
13 /avr_de/praesentation/favicon.ico 3 0.81
14 /avr_de/praesentation/favicon.gif 3 0.81
15 /avr_en/index.html 3 0.81
16 /avr_de/interrupts/int_pic.gif 3 0.81
17 /avr_de/avr_gra/8515.jpg 3 0.81
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
18 20AVR-Assemble 3 0.81
r-Dateien/links.htm
/_vti_bin/owssvr.dll?
19 3 0.81
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
20 3 0.81
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
21 20la 2 0.54
nguage_files/HARDWARE.htm
22 /cgicounter.onlinehome.de/cgi-bin/cnt.gif 2 0.54
23 /sitemap.xml 2 0.54
24 /avr_en/source/PWGSIO2.asm 2 0.54
25 /avr_gra/stk_ram.jpg 2 0.54
Sum 370 100.00

To top of page

Top 25 of 166 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 113,392 54.07
2 Mozilla/4.0 73,551 35.07
3 Opera/9.63 5,929 2.83
4 Opera/9.62 3,226 1.54
5 Mozilla/4.5 3,022 1.44
6 Yanga 1,026 0.49
7 msnbot-media/1.1 921 0.44
8 Opera/9.52 746 0.36
9 Googlebot-Image/1.0 667 0.32
10 Xaldon 662 0.32
11 msnbot/1.1 595 0.28
12 Opera/9.24 449 0.21
13 echobot/echobot-v0.5 423 0.20
14 Opera/9.60 374 0.18
15 Opera/9.51 306 0.15
16 Opera/9.50 306 0.15
17 Opera/10.00 300 0.14
18 Opera/9.61 286 0.14
19 - 251 0.12
20 Opera/9.25 198 0.09
21 123345 193 0.09
22 Opera/9.26 182 0.09
23 WebCopier v4.6 182 0.09
24 Safari5525.27.1 181 0.09
25 SapphireWebCrawler/1.0 177 0.08
Sum 209,710 100.00

To top of page

Top 25 of 390 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 62,842 29.97
2 MSIE 7.0 38,621 18.42
3 MSIE 6.0 27,944 13.33
4 Gecko 6,242 2.98
5 Firefox/3.0.5 5,931 2.83
6 Opera/9.63 5,881 2.80
7 Firefox/2.0.0.20 5,103 2.43
8 Firefox/3.0.4 3,984 1.90
9 Firefox/3.0.1 3,434 1.64
10 Opera/9.62 3,163 1.51
11 FDM 3,029 1.44
12 HTTrack 3.0x 3,020 1.44
13 Firefox/3.0.3 2,984 1.42
14 unknown 2,533 1.21
15 Slurp 2,493 1.19
16 Firefox/3.0 1,605 0.77
17 Googlebot/2.1 1,126 0.54
18 Firefox/2.0.0.18 1,090 0.52
19 msnbot-media/1.1 921 0.44
20 Opera/9.52 746 0.36
21 Slurp/3.0 722 0.34
Googlebot-
22 667 0.32
Image/1.0
23 WebSpider 2.7.b6 662 0.32
24 Firefox/2.0.0.16 656 0.31
25 MSIE 8.0 645 0.31
Sum 209,710 100.00

To top of page

Top 25 of 52 operating systems , sorted by number of files

N operating systems times %


1 Windows 89,337 42.60
2 Windows NT 5.1 66,978 31.94
3 Linux i686 13,126 6.26
4 unknown 12,738 6.07
5 Windows NT 6.0 11,577 5.52
6 Windows NT 5.0 4,145 1.98
7 Windows 98 3,691 1.76
8 Linux x86_64 1,602 0.76
9 Mac OS X 10_5_6 1,300 0.62
10 Mac OS X 10.5 1,100 0.52
11 Windows NT 5.2 677 0.32
12 Linux 555 0.26
13 Mac OS X 508 0.24
14 Windows XP 5.1 482 0.23
Mac OS X
15 458 0.22
10_4_11
16 Linux i686 251 0.12
17 Windows NT 4.0 249 0.12
18 Mac OS X 10_5_5 174 0.08
19 Mac OS X Mach-O 151 0.07
20 Mac OS X 10.4 115 0.05
21 Windows 6.0 114 0.05
22 Linux i586 83 0.04
23 SunOS i86pc 43 0.02
24 Windows CE 41 0.02
25 X11 40 0.02
Sum 209,710 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 6,374 3.04
2 01 5,056 2.41
3 02 3,506 1.67
4 03 3,013 1.44
5 04 3,970 1.89
6 05 2,991 1.43
7 06 4,147 1.98
8 07 3,964 1.89
9 08 6,083 2.90
10 09 8,544 4.07
11 10 8,974 4.28
12 11 9,903 4.72
13 12 11,880 5.66
14 13 10,886 5.19
15 14 11,945 5.70
16 15 12,017 5.73
17 16 14,050 6.70
18 17 12,630 6.02
19 18 11,844 5.65
20 19 12,942 6.17
21 20 12,626 6.02
22 21 12,364 5.90
23 22 10,955 5.22
24 23 9,046 4.31
Sum 209,710 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2009y.html (2 of 2)1/20/2009 8:02:24 PM


Weblog for http://www.avr-asm-tutorial.net

Path: Home ==> Statistic Overview ==> Overview by monthes

Overview by monthes forhttp://www.avr-asm-


tutorial.net
For more detailed informations follow these links:

● Overview by monthes,

Year Month Link to detailed information


2009 01 host names, sorted bydifferent criteria
To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/monthes.html1/20/2009 8:02:29 PM
Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Monthly sorted index ==> Log 2009m01

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2009 , month 01

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 13843 IPs and host names , sorted by number of files

N IPs and host names times %


1 41.201.123.244=(not found) 1,280 0.51
2 78.96.155.157=(not found) 1,113 0.44
3 91.205.124.9=(not found) 1,026 0.41
85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.
4 874 0.35
de
5 66.249.71.207=crawl-66-249-71-207.googlebot.com 772 0.31
6 66.249.71.205=crawl-66-249-71-205.googlebot.com 761 0.30
7 67.195.37.111=llf320022.crawl.yahoo.net 749 0.30
8 66.249.71.206=crawl-66-249-71-206.googlebot.com 747 0.30
9 72.30.87.112=llf531192.crawl.yahoo.net 708 0.28
10 85.9.121.249=(not found) 704 0.28
11 85.9.121.211=(not found) 703 0.28
12 90.149.187.3=149-187-3.oke2-bras5.adsl.tele2.no 643 0.26
13 78.46.86.53=crawl1.hetzner.itroot.de 423 0.17
14 67.195.37.164=llf320062.crawl.yahoo.net 395 0.16
15 84.161.234.174=p54A1EAAE.dip.t-dialin.net 390 0.16
16 80.191.119.218=(not found) 378 0.15
17 210.212.169.118=(not found) 377 0.15
18 84.146.240.138=p5492F08A.dip.t-dialin.net 375 0.15
19 217.85.203.141=pD955CB8D.dip.t-dialin.net 354 0.14
20 208.115.111.244=crawl3.dotnetdotcom.org 351 0.14
21 72.30.65.32=llf531371.crawl.yahoo.net 341 0.14
22 64.88.164.198=(not found) 329 0.13
23 79.193.117.235=p4FC175EB.dip.t-dialin.net 327 0.13
24 91.180.109.162=162.109-180-91.adsl-dyn.isp.belgacom.be 325 0.13
25 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 300 0.12
Sum 250,249 100.00

To top of page

Top 25 of 13843 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.205.124.9=(not found) 33,688 1.17
85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.
2 31,904 1.10
de
3 78.96.155.157=(not found) 25,173 0.87
4 41.201.123.244=(not found) 19,455 0.67
5 72.30.87.112=llf531192.crawl.yahoo.net 19,341 0.67
6 89.61.194.44=Zc22c.z.pppool.de 12,313 0.43
7 91.22.201.213=p5B16C9D5.dip.t-dialin.net 10,417 0.36
8 84.166.54.47=p54A6362F.dip0.t-ipconnect.de 10,057 0.35
9 85.9.121.249=(not found) 9,742 0.34
10 77.22.115.197=(not found) 9,674 0.33
11 67.195.37.111=llf320022.crawl.yahoo.net 9,634 0.33
12 84.161.234.174=p54A1EAAE.dip.t-dialin.net 9,287 0.32
13 72.30.65.32=llf531371.crawl.yahoo.net 8,536 0.30
14 84.146.240.138=p5492F08A.dip.t-dialin.net 8,416 0.29
15 217.85.203.141=pD955CB8D.dip.t-dialin.net 8,088 0.28
16 87.123.221.130=i577BDD82.versanet.de 8,000 0.28
17 80.142.240.222=p508EF0DE.dip.t-dialin.net 7,757 0.27
18 141.52.232.84=webproxy.fzk.de 7,622 0.26
19 87.152.175.189=p5798AFBD.dip.t-dialin.net 7,289 0.25
20 79.193.117.235=p4FC175EB.dip.t-dialin.net 6,735 0.23
21 67.195.37.164=llf320062.crawl.yahoo.net 6,729 0.23
22 82.82.209.105=dslc-082-082-209-105.pools.arcor-ip.net 6,619 0.23
23 91.12.114.10=p5B0C720A.dip.t-dialin.net 6,218 0.22
24 84.132.241.112=p5484F170.dip.t-dialin.net 6,138 0.21
25 85.127.135.21=85-127-135-21.dynamic.xdsl-line.inode.at 6,123 0.21
Sum 2,890,289 100.00

To top of page

Top 25 of 2427 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.206=crawl-66-249-71-206.googlebot.com 235 2.31
2 66.249.71.207=crawl-66-249-71-207.googlebot.com 230 2.26
3 66.249.71.205=crawl-66-249-71-205.googlebot.com 228 2.24
4 67.195.37.111=llf320022.crawl.yahoo.net 155 1.52
5 72.30.87.112=llf531192.crawl.yahoo.net 131 1.29
6 58.148.8.37=(not found) 97 0.95
7 67.195.37.164=llf320062.crawl.yahoo.net 94 0.92
8 81.52.143.16=natcrawlbloc03.net.m1.fti.net 72 0.71
9 212.143.177.197=(not found) 70 0.69
10 193.252.149.15=natcrawlbloc02.net.s1.fti.net 68 0.67
11 88.131.106.16=(not found) 66 0.65
12 81.52.143.15=natcrawlbloc01.net.m1.fti.net 66 0.65
13 72.30.65.32=llf531371.crawl.yahoo.net 55 0.54
14 81.52.143.26=natcrawlbloc05.net.m1.fti.net 55 0.54
15 72.30.78.224=llf531350.crawl.yahoo.net 47 0.46
16 193.47.80.44=crawl08.exabot.com 47 0.46
17 208.115.111.244=crawl3.dotnetdotcom.org 46 0.45
18 84.247.45.83=(not found) 44 0.43
19 203.209.252.66=hd901036.inktomisearch.com 42 0.41
20 208.44.234.50=(not found) 40 0.39
21 91.67.186.89=91-67-186-89-dynip.superkabel.de 39 0.38
22 66.235.124.3=crawler5003.ask.com 37 0.36
23 193.252.149.16=natcrawlbloc04.net.s1.fti.net 37 0.36
65.55.209.159=msnbot-65-55-209-159.search.msn.
24 37 0.36
com
25 67.195.37.157=llf320058.crawl.yahoo.net 35 0.34
Sum 10,185 100.00

To top of page

Top 25 of 116 countries of origin , sorted by number of files

N countries of origin times %


1 net 72,652 29.03
2 Germany 57,487 22.97
3 (unresolved) 45,203 18.06
4 com 14,425 5.76
5 Poland 7,565 3.02
6 Austria 6,258 2.50
7 Switzerland 4,319 1.73
8 Netherlands 3,375 1.35
9 Italy 2,657 1.06
10 India 2,269 0.91
11 Hungary 2,075 0.83
12 Czech Republic 1,819 0.73
13 Indonesia 1,802 0.72
14 Belgium 1,672 0.67
15 Greece 1,419 0.57
16 Lithuania 1,391 0.56
17 Canada 1,361 0.54
18 Brazil 1,321 0.53
19 Romania 1,319 0.53
20 Sweden 1,279 0.51
21 Australia 1,244 0.50
22 Slovak Republic 1,146 0.46
23 Russian Federation 1,135 0.45
24 Norway 1,000 0.40
25 France 995 0.40
Sum 250,249 100.00

To top of page

Top 25 of 189 pathes , sorted by number of files

N pathes times %
1 /common/ 86,146 34.42
2 /avr_gra/ 48,042 19.20
3 / 28,744 11.49
4 /avr_en/beginner/ 9,713 3.88
5 /avr_de/beginner/ 8,137 3.25
6 /avr_de/ 7,223 2.89
7 /avr_en/ 6,853 2.74
8 /avr_de/fcount/ 4,507 1.80
9 /avr_de/rechnen/ 4,414 1.76
10 /avr_en/calc/ 4,039 1.61
11 /avr_de/stepper/ 3,224 1.29
12 /avr_de/praesentation/ 3,059 1.22
13 /avr_de/quellen/ 2,275 0.91
14 /avr_en/source/ 2,229 0.89
15 /avr_en/keypad/ 2,127 0.85
16 /avr_de/keypad/ 1,954 0.78
/avr_de/rechteckgen/
17 1,937 0.77
bilder/
18 /avr_en/signalgen/pics/ 1,887 0.75
19 /gavrasm/ 1,824 0.73
20 /avr_de/interrupts/ 1,461 0.58
21 /avr_de/zeitschleifen/ 1,461 0.58
22 /avr_en/stepper/ 1,403 0.56
23 /avr_en/fcount/ 1,062 0.42
24 /akkuload/ 982 0.39
25 /gavrasm/v22/ 916 0.37
Sum 250,249 100.00

To top of page

Top 25 of 189 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 528,346 18.28
2 /avr_gra/ 506,232 17.51
3 /avr_de/intro/pdf/ 226,931 7.85
4 /avr_de/fcount/ 172,467 5.97
5 / 166,424 5.76
6 /avr_de/ 121,576 4.21
7 /avr_en/ 99,122 3.43
8 /gavrasm/v22/ 92,199 3.19
9 /avr_de/stepper/ 86,725 3.00
10 /avr_en/beginner/ 82,317 2.85
11 /avr_de/beginner/ 79,850 2.76
12 /avr_en/signalgen/pics/ 49,896 1.73
/avr_de/rechteckgen/
13 49,088 1.70
bilder/
14 /common/ 41,394 1.43
15 /avr_de/intro/ppt/ 41,356 1.43
16 /avr_en/fcount/ 41,337 1.43
17 /privat/magloop/ 40,256 1.39
18 /avr_de/rechnen/ 40,213 1.39
19 /avr_en/calc/ 36,436 1.26
20 /avr_en/stepper/ 34,989 1.21
21 /avr_en/signalgen/ 30,339 1.05
22 /avr_de/rechteckgen/ 25,268 0.87
23 /akkuload/ 24,974 0.86
24 /avr_de/interrupts/ 16,539 0.57
25 /avr_en/keypad/ 16,234 0.56
Sum 2,890,289 100.00

To top of page

Top 25 of 2116 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 12,821 5.12
2 /avr_gra/RingLogo.jpg 6,723 2.69
3 /common/app.gif 5,564 2.22
/common/knowhow.
4 5,554 2.22
gif
5 /common/akkuload.gif 5,551 2.22
/common/download.
6 5,548 2.22
gif
7 /common/clock.gif 5,534 2.21
8 /common/gavrasm.gif 5,531 2.21
9 /common/adc.gif 5,521 2.21
10 /common/calc.gif 5,520 2.21
/common/gavrasmw.
11 5,519 2.21
gif
12 /common/example.gif 5,519 2.21
13 /common/keyb.gif 5,515 2.20
14 /common/hardware.gif 5,509 2.20
15 /common/r2r.gif 5,508 2.20
16 /avr_gra/stk_lcd.jpg 5,500 2.20
17 /common/beginner.gif 5,500 2.20
18 /index.html 3,963 1.58
19 /avr_de/index.html 3,292 1.32
20 /avr_en/index.html 3,180 1.27
21 /avr_2313.gif 3,087 1.23
22 /dg4fac.gif 3,054 1.22
23 /avr-asm-tutorial.gif 3,052 1.22
24 /common/ints.gif 2,923 1.17
25 /common/delay.gif 2,917 1.17
Sum 250,249 100.00

To top of page

Top 25 of 2116 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 172,945 5.98
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 121,654 4.21
3 /avr_de/index.html 78,619 2.72
4 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 74,502 2.58
5 /avr_en/index.html 67,031 2.32
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 57,168 1.98
pdf
7 /avr_2313.gif 55,077 1.91
8 /avr_gra/tn13_exp.jpg 52,184 1.81
9 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 47,870 1.66
10 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 47,648 1.65
11 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 44,711 1.55
12 /avr_de/fcount/dscf0004.jpg 33,600 1.16
13 /dg4fac.gif 32,833 1.14
14 /avr_de/fcount/dscf0005.jpg 29,570 1.02
15 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 28,871 1.00
16 /avr_de/fcount/dscf0001.jpg 27,837 0.96
17 /avr_gra/r2r_hardware.jpg 27,283 0.94
18 /avr_gra/pwm_simul.jpg 27,278 0.94
19 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 26,550 0.92
20 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 25,616 0.89
21 /favicon.ico 25,173 0.87
22 /avr_gra/tn13_exp.gif 23,712 0.82
23 /avr_en/signalgen/pics/rectgen_wiring.jpg 22,813 0.79
24 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 22,650 0.78
25 /avr_de/intro/pdf/Teil1_Prozessor.pdf 22,253 0.77
Sum 2,890,289 100.00

To top of page

Top 25 of 515 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 3,963 7.79
2 /avr_de/index.html 3,292 6.47
3 /avr_en/index.html 3,180 6.25
4 /avr_en/beginner/LEFT.html 1,878 3.69
5 /avr_en/beginner/index.html 1,617 3.18
6 /avr_en/beginner/RIGHT.html 1,559 3.07
7 /avr_de/beginner/index.html 1,274 2.51
8 /avr_de/beginner/links.html 1,248 2.45
9 /avr_de/beginner/rechts.html 1,186 2.33
/avr_en/beginner/HARDWARE.
10 713 1.40
html
11 /avr_de/beginner/hardware.html 596 1.17
12 /avr_en/beginner/REGISTER.html 584 1.15
13 /avr_en/AVR_DAC.html 518 1.02
14 /avr_de/beginner/register.html 468 0.92
15 /avr_en/keypad/keyboard.html 464 0.91
16 /avr_en/beginner/JUMP.html 456 0.90
17 /avr_de/stepper/stepper.html 450 0.88
18 /avr_de/beginner/sprung.html 446 0.88
19 /avr_de/praesentation/index.html 429 0.84
20 /avr_de/keypad/keyboard.html 420 0.83
21 /avr_de/apps.html 413 0.81
22 /avr_de/fcount/fcount_m8.html 407 0.80
23 /avr_de/beginner/ports.html 402 0.79
24 /avr_en/beginner/PORTS.html 395 0.78
25 /avr_en/beginner/TOOLS.html 383 0.75
Sum 50,855 100.00

To top of page

Top 25 of 515 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 78,619 13.34
2 /avr_en/index.html 67,031 11.37
3 /index.html 21,168 3.59
4 /gb_new.html 12,685 2.15
5 /avr_de/dcf77uhr.html 12,542 2.13
6 /avr_de/beginner/sprung.html 12,049 2.04
7 /avr_en/beginner/RIGHT.html 11,349 1.93
8 /avr_en/beginner/JUMP.html 11,232 1.91
9 /avr_en/keypad/keyboard.html 9,611 1.63
10 /avr_de/keypad/keyboard.html 8,536 1.45
11 /avr_en/beginner/CALC.html 8,242 1.40
12 /avr_de/beginner/rechts.html 8,224 1.40
13 /avr_de/beginner/rechnen.html 8,181 1.39
14 /avr_en/AVR_DAC.html 7,551 1.28
15 /avr_en/beginner/LEFT.html 7,282 1.24
16 /avr_en/beginner/REGISTER.html 7,022 1.19
17 /avr_de/stepper/stepper.html 6,784 1.15
18 /avr_de/beginner/pdetail.html 6,570 1.11
19 /avr_de/beginner/commands.html 6,425 1.09
20 /sitemap_de.html 6,420 1.09
/avr_de/rechteckgen/rectgen_m8.
21 6,376 1.08
html
22 /avr_en/signalgen/rectgen_m8.html 6,241 1.06
23 /avr_de/beginner/hardware.html 6,204 1.05
/avr_en/beginner/COMMANDS.
24 6,050 1.03
html
25 /avr_en/beginner/HARDWARE.html 5,985 1.02
Sum 589,467 100.00

To top of page

Top 25 of 809 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 6,723 17.51
2 /avr_gra/stk_lcd.jpg 5,500 14.32
3 /avr_gra/8515.jpg 1,273 3.32
4 /avr_gra/exp2313g.jpg 1,270 3.31
5 /avr_gra/tn13_exp.jpg 1,207 3.14
6 /avr_gra/avr_isp.jpg 1,204 3.14
7 /avr_gra/exp_2313.jpg 1,197 3.12
8 /avr_gra/r2r_wave.jpg 902 2.35
9 /avr_gra/r2r_sawtooth.jpg 807 2.10
10 /avr_gra/r2r_hardware.jpg 765 1.99
11 /avr_gra/r2r_triangle.jpg 756 1.97
12 /avr_gra/r2r_sawtoothupperbound.jpg 750 1.95
13 /avr_gra/r2r_sawtooth741.jpg 750 1.95
14 /avr_gra/r2r_upperbound.jpg 746 1.94
15 /avr_gra/AT90S8515.jpg 618 1.61
16 /avr_gra/apps.jpg 551 1.44
17 /avr_gra/pwm_simul.jpg 484 1.26
18 /avr_gra/adc8conn.jpg 477 1.24
19 /akkuload/dscf0030s.jpg 473 1.23
20 /avr_de/stepper/stepper_sm.jpg 466 1.21
21 /avr_de/stepper/supply.jpg 433 1.13
22 /avr_de/stepper/kp4m4-001.jpg 430 1.12
23 /avr_de/stepper/driver.jpg 426 1.11
/avr_en/signalgen/pics/rectgen_280.
24 403 1.05
jpg
25 /avr_de/praesentation/zuendtester.jpg 401 1.04
Sum 38,397 100.00

To top of page

Top 25 of 442 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 5,564 4.12
/common/knowhow.
2 5,554 4.12
gif
3 /common/akkuload.gif 5,551 4.11
/common/download.
4 5,547 4.11
gif
5 /common/clock.gif 5,534 4.10
6 /common/gavrasm.gif 5,531 4.10
7 /common/adc.gif 5,521 4.09
8 /common/calc.gif 5,520 4.09
/common/gavrasmw.
9 5,519 4.09
gif
10 /common/example.gif 5,519 4.09
11 /common/keyb.gif 5,515 4.09
12 /common/hardware.gif 5,509 4.08
13 /common/r2r.gif 5,508 4.08
14 /common/beginner.gif 5,500 4.08
15 /avr_2313.gif 3,087 2.29
16 /dg4fac.gif 3,054 2.26
17 /avr-asm-tutorial.gif 3,052 2.26
18 /common/ints.gif 2,923 2.17
19 /common/delay.gif 2,917 2.16
20 /common/tn13.gif 2,913 2.16
21 /avr_gra/2313.gif 2,690 1.99
22 /avr_gra/exp2313.gif 1,224 0.91
23 /avr_gra/avr_isp.gif 1,202 0.89
24 /avr_gra/isp6pin.gif 1,197 0.89
25 /avr_gra/tn13_exp.gif 1,196 0.89
Sum 134,921 100.00

To top of page

Top 25 of 197 entry pages , sorted by number of files

N entry pages times %


1 /index.html 1,901 17.57
2 /avr_en/index.html 1,102 10.19
3 /avr_de/index.html 912 8.43
4 /avr_en/beginner/index.html 492 4.55
5 /avr_en/AVR_DAC.html 302 2.79
6 /avr_de/beginner/index.html 289 2.67
7 /avr_de/stepper/stepper.html 248 2.29
8 /avr_en/beginner/HARDWARE.html 202 1.87
9 /avr_de/fcount/fcount_m8.html 190 1.76
10 /avr_de/avr_dac.html 181 1.67
11 /avr_de/beginner/hardware.html 173 1.60
12 /avr_de/keypad/keyboard.html 172 1.59
13 /avr_en/keypad/keyboard.html 162 1.50
/avr_de/rechteckgen/rectgen_m8.
14 150 1.39
html
15 /avr_en/signalgen/rectgen_m8.html 149 1.38
16 /avr_de/intro/index.html 137 1.27
17 /avr_en/AVR_ADC500.html 122 1.13
18 /gb_new.html 117 1.08
19 /avr_de/rechnen/konversion.html 111 1.03
20 /avr_de/rechnen/multiplikation.html 91 0.84
21 /avr_de/avr_adc500.html 89 0.82
22 /avr_en/beginner/REGISTER.html 86 0.80
23 /avr_de/beginner/rechnen.html 84 0.78
24 /akkuload/de/index.html 83 0.77
25 /privat/stechlin/index.html 82 0.76
Sum 10,817 100.00

To top of page

Top 25 of 271 cheat pages , sorted by number of files

N cheat pages times %


1 1,228 8.87
2 /index.html 1,137 8.21
3 /avr_en/index.html 978 7.06
4 /avr_de/index.html 866 6.26
5 /avr_en/AVR_DAC.html 345 2.49
6 /avr_en/beginner/RIGHT.html 306 2.21
7 /avr_en/beginner/HARDWARE.html 300 2.17
8 /avr_de/stepper/stepper.html 269 1.94
9 /avr_en/keypad/keyboard.html 236 1.70
10 /avr_de/beginner/hardware.html 227 1.64
11 /avr_de/keypad/keyboard.html 226 1.63
12 /avr_de/fcount/fcount_m8.html 209 1.51
13 /avr_de/avr_dac.html 207 1.50
14 /avr_de/beginner/rechts.html 188 1.36
15 /avr_en/beginner/REGISTER.html 168 1.21
16 /akkuload/de/index.html 150 1.08
/avr_de/rechteckgen/rectgen_m8.
17 146 1.05
html
18 /avr_en/AVR_ADC500.html 142 1.03
19 /avr_de/beginner/sprung.html 141 1.02
20 /avr_de/praesentation/index.html 134 0.97
21 /avr_en/beginner/SRAM.html 130 0.94
22 /avr_de/intro/index.html 129 0.93
23 /avr_en/beginner/JUMP.html 128 0.92
24 /avr_en/signalgen/rectgen_m8.html 124 0.90
25 /avr_de/beginner/rechnen.html 124 0.90
Sum 13,843 100.00

To top of page

Top 25 of 200 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 4,045 15.46
2 /avr_en/beginner/index.html 3,090 11.81
3 /avr_de/beginner/index.html 2,098 8.02
4 / 1,875 7.17
5 /avr_en/index.html 1,649 6.30
6 /avr_en/beginner/RIGHT.html 1,348 5.15
7 /avr_en/ 1,289 4.93
8 /avr_de/beginner/rechts.html 1,249 4.77
9 /avr_en/beginner/LEFT.html 1,027 3.93
10 /avr_de/beginner/links.html 751 2.87
11 /sitemap_de.html 741 2.83
12 /sitemap_en.html 552 2.11
13 /index.html 459 1.75
14 /avr_de/apps.html 423 1.62
15 /avr_de/interrupts/index.html 405 1.55
16 /avr_de/avr_tut.html 307 1.17
17 /avr_de/zeitschleifen/index.html 289 1.10
18 /avr_en/calc/index.html 242 0.93
19 /avr_de/ 242 0.93
20 /avr_en/AVR_TUT.html 226 0.86
21 /avr_en/APPS.html 195 0.75
22 /avr_de/beginner/commands.html 165 0.63
23 /avr_de/rechnen/index.html 153 0.58
/avr_en/signalgen/rectgen_m8.
24 153 0.58
html
25 /weblox_de/index.html 152 0.58
Sum 26,162 100.00

To top of page

Top 25 of 802 external referrers , sorted by number of files

N external referrers times %


1 - 12,893 82.07
2 http://www.mikrocontroller.net/articles/AVR 112 0.71
3 http://www.webring.com/hub?ring=avr 96 0.61
4 http://www.elektroda.pl/rtvforum/viewtopic.php?t=1191671 82 0.52
5 http://www.dg4fac.de/linksunten.html 63 0.40
6 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 54 0.34
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 51 0.32
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
8 43 0.27
kurs.htm
9 http://de.wikipedia.org/wiki/R2R-Netzwerk 41 0.26
10 http://www.dg4fac.de/rechtsunten.html 38 0.24
11 http://www.serasidis.gr/link.htm 38 0.24
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
12 37 0.24
ESC_by1_bz0_bs0.html
13 http://www.mikrocontroller.net/articles/Linksammlung 34 0.22
14 http://www.educypedia.be/electronics/avr.htm 33 0.21
15 http://avr-asm.tripod.com/ 33 0.21
16 http://www.rowalt.de/mc/avr/linksd.htm 30 0.19
http://www.avrfreaks.net/index.php?
17 name=PNphpBB2&file=viewtopic&t=7067 29 0.18
3
18 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 27 0.17
19 http://www.dg4fac.de/stechlin/index.html 24 0.15
20 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 23 0.15
http://electrons.psychogenic.com/modules/arms/art/3/
21 AVRGCCProgrammingG 22 0.14
uide.php
22 http://www.raw.to/rubriken/private_elektronik.html 22 0.14
23 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 22 0.14
24 http://blackstrom.derschwarz.de/avr/avr/index.shtml 19 0.12
http://www.avrfreaks.net/index.php?
25 name=PNphpBB2&file=viewtopic&t=3698 17 0.11
8
Sum 15,709 100.00

To top of page

Top 25 of 160 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 3,783 45.21
2 http://www.google.com 1,363 16.29
3 http://www.google.at 315 3.76
4 http://www.google.co.in 251 3.00
5 http://www.google.nl 171 2.04
6 http://www.google.pl 168 2.01
7 http://www.google.ch 165 1.97
8 http://www.google.co.uk 137 1.64
9 http://www.google.ca 118 1.41
10 http://www.google.ro 96 1.15
11 http://www.google.se 84 1.00
http://www.google.com.
12 83 0.99
au
13 http://www.google.co.id 68 0.81
14 http://www.google.be 62 0.74
15 http://www.google.fi 56 0.67
http://de.search.yahoo.
16 55 0.66
com
17 http://search.yahoo.com 54 0.65
18 http://www.google.hu 52 0.62
19 http://www.google.it 52 0.62
20 http://www.google.com.tr 50 0.60
21 http://www.google.fr 49 0.59
22 http://www.google.lt 48 0.57
23 http://www.google.gr 46 0.55
24 http://www.google.es 45 0.54
25 http://www.google.sk 44 0.53
Sum 8,368 100.00

To top of page

Top 25 of 5076 search strings , sorted by number of files

N search strings times %


1 avr tutorial 230 2.75
2 avr assembler 162 1.94
3 avr 124 1.48
4 assembler 79 0.94
5 attiny13 75 0.90
6 avr programming 70 0.84
7 avr assembly 49 0.59
8 avr asm 48 0.57
assembler
9 47 0.56
commands
10 assembler tutorial 44 0.53
11 AVR tutorial 38 0.45
12 ATtiny13 36 0.43
13 atmega8 36 0.43
avr assembler
14 35 0.42
tutorial
15 atmel avr 34 0.41
16 avr asm tutorial 33 0.39
17 stk500 30 0.36
18 AVR 30 0.36
19 avr codes 24 0.29
20 Assembler 23 0.27
21 avr assembly tutorial 22 0.26
22 gavrasm 22 0.26
23 atmel assembler 22 0.26
24 assembler lernen 20 0.24
25 assembler avr 17 0.20
Sum 8,368 100.00

To top of page

Top 10 of 10 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 223,460 89.30
2 304 Not changed 24,255 9.69
3 206 Partial information 1,428 0.57
4 301 Permanently moved 581 0.23
5 404 File not found 409 0.16

http://www.avr-asm-tutorial.net/weblox_en/2009m01.html (1 of 2)1/20/2009 8:02:43 PM


Weblog statistic for http://www.avr-asm-tutorial.net

6 405 Method not allowed 51 0.02


7 403 Forbidden 35 0.01
8 300 Multiple choices 20 0.01
9 xxx Unknown error 7 0.00
10 xxx Unknown error 3 0.00
Sum 250,249 100.00

To top of page

Top 25 of 131 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 144 35.21
2 /beginner_de.pdf 44 10.76
3 /avr_de/intro/ppt/beispiel10_snd.wav 14 3.42
4 /avr_de/interrupts/undefined 10 2.44
5 /fcount/fcount_m8.html 10 2.44
/_vti_bin/owssvr.dll?
6 9 2.20
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
7 9 2.20
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
8 20la 8 1.96
nguage_files/LEFT.htm
9 /hostnamehttp://www.poliauto.ca//media/test.txt?? 6 1.47
10 /keypad/gb_new.html 5 1.22
11 /avr_de/keypad/gb_new.html 4 0.98
12 /_vti_inf.html 4 0.98
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
13 20la 3 0.73
nguage_files/HARDWARE.htm
14 /avr_de/praesentation/favicon.ico 3 0.73
15 /avr_de/praesentation/favicon.gif 3 0.73
16 /avr_en/index.html 3 0.73
17 /avr_de/interrupts/int_pic.gif 3 0.73
18 /avr_de/avr_gra/8515.jpg 3 0.73
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
19 20AVR-Assemble 3 0.73
r-Dateien/links.htm
/_vti_bin/owssvr.dll?
20 3 0.73
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
21 3 0.73
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
22 /cgicounter.onlinehome.de/cgi-bin/cnt.gif 2 0.49
23 /sitemap.xml 2 0.49
24 /avr_en/source/PWGSIO2.asm 2 0.49
25 /avr_gra/stk_ram.jpg 2 0.49
Sum 409 100.00

To top of page

Top 25 of 182 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 135,492 54.14
2 Mozilla/4.0 88,689 35.44
3 Opera/9.63 6,819 2.72
4 Opera/9.62 3,622 1.45
5 Mozilla/4.5 3,069 1.23
6 msnbot-media/1.1 1,203 0.48
7 Yanga 1,026 0.41
Googlebot-
8 945 0.38
Image/1.0
9 Opera/9.52 845 0.34
10 msnbot/1.1 730 0.29
11 Xaldon 662 0.26
12 Opera/9.24 514 0.21
13 Opera/9.60 456 0.18
14 Opera/10.00 447 0.18
echobot/echobot-
15 423 0.17
v0.5
16 Opera/9.51 410 0.16
17 Opera/9.61 395 0.16
18 Opera/9.25 322 0.13
19 Opera/9.50 306 0.12
20 - 260 0.10
21 Opera/9.26 220 0.09
22 Safari5525.27.1 212 0.08
23 Opera/9.27 205 0.08
24 123345 193 0.08
25 WebCopier v4.6 182 0.07
Sum 250,249 100.00

To top of page

Top 25 of 417 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 75,780 30.28
2 MSIE 7.0 48,095 19.22
3 MSIE 6.0 32,266 12.89
4 Gecko 7,596 3.04
5 Firefox/3.0.5 7,142 2.85
6 Opera/9.63 6,766 2.70
7 Firefox/2.0.0.20 5,841 2.33
8 Firefox/3.0.4 4,526 1.81
9 Firefox/3.0.1 4,022 1.61
10 FDM 3,687 1.47
11 Opera/9.62 3,559 1.42
12 Firefox/3.0.3 3,541 1.41
13 HTTrack 3.0x 3,067 1.23
14 Slurp 3,001 1.20
15 unknown 2,784 1.11
16 Firefox/3.0 1,809 0.72
17 Googlebot/2.1 1,321 0.53
18 Firefox/2.0.0.18 1,245 0.50
19 msnbot-media/1.1 1,203 0.48
20 MSIE 8.0 957 0.38
Googlebot-
21 945 0.38
Image/1.0
22 Opera/9.52 845 0.34
23 Slurp/3.0 844 0.34
24 Firefox/2.0.0.11 767 0.31
25 Firefox/2.0.0.16 744 0.30
Sum 250,249 100.00

To top of page

Top 25 of 57 operating systems , sorted by number of files

N operating systems times %


1 Windows 106,639 42.61
2 Windows NT 5.1 80,431 32.14
3 Linux i686 15,692 6.27
4 unknown 14,738 5.89
5 Windows NT 6.0 14,169 5.66
6 Windows NT 5.0 4,712 1.88
7 Windows 98 3,833 1.53
8 Linux x86_64 2,210 0.88
9 Mac OS X 10_5_6 1,731 0.69
10 Mac OS X 10.5 1,288 0.51
11 Windows NT 5.2 730 0.29
12 Linux 625 0.25
13 Mac OS X 617 0.25
14 Windows XP 5.1 546 0.22
Mac OS X
15 458 0.18
10_4_11
16 Linux i686 268 0.11
17 Windows NT 4.0 249 0.10
18 Mac OS X 10_5_5 214 0.09
19 Mac OS X Mach-O 151 0.06
20 Linux i586 140 0.06
21 Windows 6.0 130 0.05
22 Mac OS X 10.4 122 0.05
23 Windows NT 6.1 121 0.05
24 Windows CE 108 0.04
25 X11 48 0.02
Sum 250,249 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 7,664 3.06
2 01 5,914 2.36
3 02 4,079 1.63
4 03 3,710 1.48
5 04 4,527 1.81
6 05 3,688 1.47
7 06 4,715 1.88
8 07 4,926 1.97
9 08 7,278 2.91
10 09 10,212 4.08
11 10 10,431 4.17
12 11 12,167 4.86
13 12 14,948 5.97
14 13 13,344 5.33
15 14 14,252 5.70
16 15 14,442 5.77
17 16 16,895 6.75
18 17 14,605 5.84
19 18 14,412 5.76
20 19 14,779 5.91
21 20 15,382 6.15
22 21 14,618 5.84
23 22 12,789 5.11
24 23 10,472 4.18
Sum 250,249 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2009m01.html (2 of 2)1/20/2009 8:02:43 PM


Weblog for http://www.avr-asm-tutorial.net

Path: Home ==> Statistic Overview ==> Overview by weeks

Overview by weeks forhttp://www.avr-asm-


tutorial.net
For more detailed informations follow these links:

● Overview by weeks.

Year Week Link to detailed information


2009 03 host names, sorted bydifferent criteria
02 host names, sorted bydifferent criteria
01 host names, sorted bydifferent criteria
To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/weeks.html1/20/2009 8:02:48 PM
Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2009w03

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2009 , week 03

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 6136 IPs and host names , sorted by number of files

N IPs and host names times %


1 78.96.155.157=(not found) 971 0.94
2 85.9.121.249=(not found) 704 0.68
3 85.9.121.211=(not found) 703 0.68
4 91.205.124.9=(not found) 515 0.50
5 84.161.234.174=p54A1EAAE.dip.t-dialin.net 390 0.38
6 210.212.169.118=(not found) 377 0.36
7 80.191.119.218=(not found) 359 0.35
8 72.30.65.32=llf531371.crawl.yahoo.net 341 0.33
9 66.249.71.205=crawl-66-249-71-205.googlebot.com 334 0.32
10 66.249.71.207=crawl-66-249-71-207.googlebot.com 320 0.31
11 66.249.71.206=crawl-66-249-71-206.googlebot.com 312 0.30
92.75.230.63=dslb-092-075-230-063.pools.arcor-ip.
12 299 0.29
net
13 84.73.51.19=84-73-51-19.dclient.hispeed.ch 285 0.27
14 83.30.253.55=cgz55.neoplus.adsl.tpnet.pl 278 0.27
15 87.123.221.130=i577BDD82.versanet.de 269 0.26
16 217.93.161.1=pD95DA101.dip0.t-ipconnect.de 258 0.25
17 67.195.37.164=llf320062.crawl.yahoo.net 244 0.24
18 64.88.164.198=(not found) 239 0.23
19 72.30.78.224=llf531350.crawl.yahoo.net 226 0.22
20 217.77.28.236=77-28-236.elekta.lt 216 0.21
21 91.190.226.204=(not found) 214 0.21
22 91.9.149.205=p5B0995CD.dip0.t-ipconnect.de 205 0.20
23 87.170.249.187=p57AAF9BB.dip.t-dialin.net 203 0.20
24 91.83.16.38=91.83.16.38.pool.invitel.hu 190 0.18
25 91.8.94.236=p5B085EEC.dip.t-dialin.net 185 0.18
Sum 103,699 100.00

To top of page

Top 25 of 6136 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 78.96.155.157=(not found) 24,026 2.02
2 91.205.124.9=(not found) 16,366 1.37
3 84.166.54.47=p54A6362F.dip0.t-ipconnect.de 10,057 0.84
4 85.9.121.249=(not found) 9,742 0.82
5 84.161.234.174=p54A1EAAE.dip.t-dialin.net 9,287 0.78
6 72.30.65.32=llf531371.crawl.yahoo.net 8,536 0.72
7 87.123.221.130=i577BDD82.versanet.de 8,000 0.67
8 141.52.232.84=webproxy.fzk.de 7,622 0.64
9 213.214.12.100=(not found) 5,871 0.49
10 78.51.73.242=f051073242.adsl.alicedsl.de 5,739 0.48
11 87.153.196.10=p5799C40A.dip.t-dialin.net 5,536 0.46
12 213.133.123.120=gw1.etcconnect.net 5,391 0.45
13 84.188.114.224=p54BC72E0.dip.t-dialin.net 5,139 0.43
14 72.30.78.224=llf531350.crawl.yahoo.net 4,800 0.40
15 78.54.0.181=f054000181.adsl.alicedsl.de 4,732 0.40
16 80.191.119.218=(not found) 4,703 0.39
17 67.195.37.164=llf320062.crawl.yahoo.net 4,415 0.37
18 77.180.52.173=koln-4db434ad.pool.einsundeins.de 4,381 0.37
88.65.171.167=dslb-088-065-171-167.pools.arcor-ip.
19 4,266 0.36
net
20 91.9.171.32=p5B09AB20.dip0.t-ipconnect.de 3,981 0.33
21 77.22.115.197=(not found) 3,884 0.33
22 92.75.230.63=dslb-092-075-230-063.pools.arcor-ip.net 3,842 0.32
23 91.45.204.106=p5B2DCC6A.dip.t-dialin.net 3,796 0.32
24 87.123.139.230=i577B8BE6.versanet.de 3,771 0.32
25 217.91.23.136=pd95b1788.dip0.t-ipconnect.de 3,715 0.31
Sum 1,190,911 100.00

To top of page

Top 25 of 1043 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.205=crawl-66-249-71-205.googlebot.com 111 2.84
2 66.249.71.207=crawl-66-249-71-207.googlebot.com 101 2.58
3 66.249.71.206=crawl-66-249-71-206.googlebot.com 95 2.43
4 72.30.65.32=llf531371.crawl.yahoo.net 55 1.41
5 67.195.37.164=llf320062.crawl.yahoo.net 49 1.25
6 72.30.78.224=llf531350.crawl.yahoo.net 47 1.20
7 58.148.8.37=(not found) 43 1.10
8 91.67.186.89=91-67-186-89-dynip.superkabel.de 28 0.72
9 88.131.106.16=(not found) 26 0.67
10 74.6.22.172=llf520058.crawl.yahoo.net 26 0.67
11 212.143.177.197=(not found) 24 0.61
12 208.44.234.50=(not found) 21 0.54
13 81.52.143.16=natcrawlbloc03.net.m1.fti.net 19 0.49
14 72.30.142.174=llf531090.crawl.yahoo.net 19 0.49
65.55.209.165=msnbot-65-55-209-165.search.msn.
15 19 0.49
com
16 67.195.37.170=llf320040.crawl.yahoo.net 18 0.46
17 66.235.124.3=crawler5003.ask.com 18 0.46
18 81.52.143.15=natcrawlbloc01.net.m1.fti.net 18 0.46
19 203.209.252.66=hd901036.inktomisearch.com 18 0.46
20 67.195.37.175=llf320066.crawl.yahoo.net 16 0.41
21 67.195.37.189=llf320053.crawl.yahoo.net 16 0.41
65.55.209.151=msnbot-65-55-209-151.search.msn.
22 16 0.41
com
65.55.209.152=msnbot-65-55-209-152.search.msn.
23 16 0.41
com
65.55.209.156=msnbot-65-55-209-156.search.msn.
24 16 0.41
com
25 81.52.143.26=natcrawlbloc05.net.m1.fti.net 15 0.38
Sum 3,909 100.00

To top of page

Top 25 of 93 countries of origin , sorted by number of files

N countries of origin times %


1 net 28,193 27.19
2 Germany 23,570 22.73
3 (unresolved) 20,914 20.17
4 com 6,249 6.03
5 Poland 3,585 3.46
6 Austria 2,748 2.65
7 Switzerland 1,973 1.90
8 Netherlands 1,481 1.43
9 Italy 1,316 1.27
10 Hungary 920 0.89
11 Czech Republic 822 0.79
12 Canada 746 0.72
13 Lithuania 666 0.64
14 Indonesia 624 0.60
15 Belgium 604 0.58
16 Greece 579 0.56
17 Romania 560 0.54
18 France 554 0.53
19 India 547 0.53
20 edu 525 0.51
21 Sweden 498 0.48
22 Brazil 463 0.45
23 Russian Federation 449 0.43
24 Australia 409 0.39
25 Finland 387 0.37
Sum 103,699 100.00

To top of page

Top 25 of 122 pathes , sorted by number of files

N pathes times %
1 /common/ 34,945 33.70
2 /avr_gra/ 20,439 19.71
3 / 11,710 11.29
4 /avr_en/beginner/ 4,003 3.86
5 /avr_de/beginner/ 3,422 3.30
6 /avr_en/ 2,840 2.74
7 /avr_de/ 2,766 2.67
8 /avr_de/fcount/ 2,183 2.11
9 /avr_de/rechnen/ 1,856 1.79
10 /avr_en/calc/ 1,799 1.73
11 /avr_de/stepper/ 1,338 1.29
12 /avr_de/praesentation/ 1,104 1.06
13 /avr_en/keypad/ 881 0.85
14 /avr_en/fcount/ 860 0.83
15 /avr_de/quellen/ 820 0.79
16 /avr_en/source/ 820 0.79
17 /avr_de/rechteckgen/bilder/ 805 0.78
18 /avr_en/signalgen/pics/ 789 0.76
19 /avr_de/keypad/ 758 0.73
20 /gavrasm/ 674 0.65
21 /avr_en/stepper/ 603 0.58
22 /avr_de/interrupts/ 586 0.57
23 /avr_de/zeitschleifen/ 542 0.52
/privat/stechlin/rundgang/
24 439 0.42
thumbs/
25 /akkuload/ 430 0.41
Sum 103,699 100.00

To top of page

Top 25 of 122 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_gra/ 224,345 18.84
2 /avr_de/praesentation/ 191,559 16.09
3 /avr_de/fcount/ 82,117 6.90
4 /avr_de/intro/pdf/ 81,898 6.88
5 / 66,536 5.59
6 /avr_de/ 47,108 3.96
7 /avr_en/ 41,495 3.48
8 /avr_en/beginner/ 35,414 2.97
9 /avr_de/stepper/ 35,250 2.96
10 /avr_de/beginner/ 34,385 2.89
11 /gavrasm/v22/ 33,631 2.82
12 /avr_en/fcount/ 33,298 2.80
13 /avr_de/rechteckgen/bilder/ 20,646 1.73
14 /avr_en/signalgen/pics/ 20,160 1.69
15 /privat/magloop/ 19,336 1.62
16 /avr_de/intro/ppt/ 18,185 1.53
17 /common/ 16,646 1.40
18 /avr_en/calc/ 16,178 1.36
19 /avr_de/rechnen/ 16,122 1.35
20 /avr_en/stepper/ 15,665 1.32
21 /avr_en/signalgen/ 11,645 0.98
22 /akkuload/ 10,525 0.88
23 /avr_de/rechteckgen/ 10,348 0.87
/privat/kranichstein/
24 8,066 0.68
thumbs/
25 /avr_de/interrupts/ 6,805 0.57
Sum 1,190,911 100.00

To top of page

Top 25 of 1583 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 5,175 4.99
2 /avr_gra/RingLogo.jpg 2,727 2.63
3 /common/app.gif 2,263 2.18
/common/knowhow.
4 2,255 2.17
gif
5 /common/akkuload.gif 2,252 2.17
6 /common/keyb.gif 2,250 2.17
7 /common/gavrasm.gif 2,247 2.17
/common/download.
8 2,247 2.17
gif
9 /common/calc.gif 2,245 2.16
10 /common/example.gif 2,244 2.16
11 /common/adc.gif 2,244 2.16
12 /common/clock.gif 2,244 2.16
13 /common/beginner.gif 2,239 2.16
/common/gavrasmw.
14 2,239 2.16
gif
15 /common/r2r.gif 2,239 2.16
16 /avr_gra/stk_lcd.jpg 2,237 2.16
17 /common/hardware.gif 2,237 2.16
18 /index.html 1,579 1.52
19 /avr_en/index.html 1,325 1.28
20 /avr_de/index.html 1,308 1.26
21 /avr_2313.gif 1,269 1.22
22 /dg4fac.gif 1,240 1.20
23 /avr-asm-tutorial.gif 1,238 1.19
24 /common/ints.gif 1,171 1.13
25 /common/delay.gif 1,167 1.13
Sum 103,699 100.00

To top of page

Top 25 of 1583 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 61,778 5.19
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 37,649 3.16
3 /avr_de/index.html 31,527 2.65
4 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 29,992 2.52
5 /avr_en/index.html 28,052 2.36
6 /avr_2313.gif 22,273 1.87
7 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 20,376 1.71
8 /avr_gra/tn13_exp.jpg 20,040 1.68
/avr_de/praesentation/Teil_5b_Beispiel01_02.
9 19,948 1.68
pdf
10 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 19,839 1.67
11 /avr_de/fcount/dscf0004.jpg 16,106 1.35
12 /avr_de/fcount/dscf0005.jpg 14,061 1.18
13 /avr_de/fcount/dscf0001.jpg 13,270 1.11
14 /dg4fac.gif 13,222 1.11
15 /avr_gra/r2r_hardware.jpg 12,848 1.08
16 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 12,348 1.04
17 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 11,642 0.98
18 /avr_gra/pwm_simul.jpg 11,484 0.96
19 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 11,088 0.93
20 /avr_gra/ports_m8.gif 10,923 0.92
21 /favicon.ico 10,148 0.85
22 /avr_de/fcount/fcount.jpg 10,148 0.85
23 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 9,896 0.83
24 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 9,512 0.80
25 /avr_en/signalgen/pics/rectgen_wiring.jpg 9,180 0.77
Sum 1,190,911 100.00

To top of page

Top 25 of 348 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,579 7.68
2 /avr_en/index.html 1,325 6.45
3 /avr_de/index.html 1,308 6.36
4 /avr_en/beginner/index.html 691 3.36
5 /avr_en/beginner/LEFT.html 666 3.24
6 /avr_en/beginner/RIGHT.html 649 3.16
7 /avr_de/beginner/index.html 533 2.59
8 /avr_de/beginner/links.html 521 2.54
9 /avr_de/beginner/rechts.html 499 2.43
/avr_en/beginner/HARDWARE.
10 289 1.41
html
11 /avr_en/beginner/REGISTER.html 258 1.26
12 /avr_en/AVR_DAC.html 234 1.14
13 /avr_de/beginner/hardware.html 220 1.07
14 /avr_de/beginner/register.html 203 0.99
15 /avr_en/beginner/JUMP.html 200 0.97
16 /avr_de/beginner/sprung.html 197 0.96
17 /avr_de/fcount/fcount_m8.html 196 0.95
18 /avr_de/beginner/ports.html 186 0.91
19 /avr_en/keypad/keyboard.html 184 0.90
20 /avr_de/stepper/stepper.html 182 0.89
21 /avr_en/beginner/TOOLS.html 166 0.81
22 /avr_de/beginner/commands.html 165 0.80
23 /avr_de/apps.html 165 0.80
24 /avr_en/beginner/SRAM.html 161 0.78
25 /avr_de/praesentation/index.html 157 0.76
Sum 20,550 100.00

To top of page

Top 25 of 348 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 31,527 13.26
2 /avr_en/index.html 28,052 11.80
3 /index.html 8,454 3.56
4 /avr_de/beginner/sprung.html 5,353 2.25
5 /avr_en/beginner/JUMP.html 4,966 2.09
6 /gb_new.html 4,937 2.08
7 /avr_en/beginner/RIGHT.html 4,781 2.01
8 /avr_de/dcf77uhr.html 4,293 1.81
9 /avr_en/keypad/keyboard.html 3,806 1.60
10 /avr_de/beginner/rechnen.html 3,753 1.58
11 /avr_en/AVR_DAC.html 3,562 1.50
12 /avr_de/beginner/rechts.html 3,392 1.43
13 /avr_en/beginner/CALC.html 3,354 1.41
14 /avr_de/keypad/keyboard.html 3,300 1.39
15 /avr_de/beginner/commands.html 3,146 1.32
16 /avr_en/beginner/LEFT.html 3,132 1.32
17 /avr_en/beginner/REGISTER.html 3,094 1.30
18 /avr_de/beginner/ports.html 2,907 1.22
19 /avr_de/beginner/pdetail.html 2,726 1.15
20 /avr_de/stepper/stepper.html 2,672 1.12
/avr_de/rechteckgen/rectgen_m8.
21 2,640 1.11
html
22 /avr_en/beginner/PDETAIL.html 2,632 1.11
/avr_en/beginner/COMMANDS.
23 2,552 1.07
html
24 /avr_de/fcount/fcount_m8.html 2,520 1.06
25 /avr_de/avr_dac.html 2,520 1.06
Sum 237,772 100.00

To top of page

Top 25 of 565 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,727 16.52
2 /avr_gra/stk_lcd.jpg 2,237 13.55
3 /avr_gra/8515.jpg 566 3.43
4 /avr_gra/tn13_exp.jpg 469 2.84
5 /avr_gra/avr_isp.jpg 468 2.83
6 /avr_gra/exp2313g.jpg 466 2.82
7 /avr_gra/exp_2313.jpg 464 2.81
8 /avr_gra/r2r_wave.jpg 425 2.57
9 /avr_gra/r2r_sawtooth.jpg 374 2.27
10 /avr_gra/r2r_triangle.jpg 351 2.13
11 /avr_gra/r2r_hardware.jpg 350 2.12
12 /avr_gra/r2r_sawtooth741.jpg 346 2.10
13 /avr_gra/r2r_upperbound.jpg 345 2.09
/avr_gra/r2r_sawtoothupperbound.
14 344 2.08
jpg
15 /avr_gra/AT90S8515.jpg 238 1.44
16 /avr_gra/apps.jpg 222 1.34
17 /akkuload/dscf0030s.jpg 208 1.26
18 /avr_gra/pwm_simul.jpg 204 1.24
19 /avr_gra/adc8conn.jpg 199 1.21
20 /avr_de/stepper/stepper_sm.jpg 195 1.18
21 /avr_de/fcount/fcount_sm.jpg 185 1.12
22 /avr_de/fcount/dscf0001.jpg 184 1.11
23 /avr_de/fcount/dscf0005.jpg 183 1.11
24 /avr_de/fcount/fcount.jpg 182 1.10
25 /avr_de/fcount/dscf0004.jpg 182 1.10
Sum 16,510 100.00

To top of page

Top 25 of 383 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 2,263 4.03
/common/knowhow.
2 2,255 4.01
gif
3 /common/akkuload.gif 2,252 4.01
4 /common/keyb.gif 2,250 4.01
5 /common/gavrasm.gif 2,247 4.00
/common/download.
6 2,247 4.00
gif
7 /common/calc.gif 2,245 4.00
8 /common/example.gif 2,244 4.00
9 /common/adc.gif 2,244 4.00
10 /common/clock.gif 2,244 4.00
11 /common/beginner.gif 2,239 3.99
/common/gavrasmw.
12 2,239 3.99
gif
13 /common/r2r.gif 2,239 3.99
14 /common/hardware.gif 2,237 3.98
15 /avr_2313.gif 1,269 2.26
16 /dg4fac.gif 1,240 2.21
17 /avr-asm-tutorial.gif 1,238 2.20
18 /common/ints.gif 1,171 2.08
19 /common/delay.gif 1,167 2.08
20 /common/tn13.gif 1,162 2.07
21 /avr_gra/2313.gif 1,148 2.04
22 /avr_gra/exp2313.gif 478 0.85
23 /avr_gra/avr_isp.gif 469 0.84
24 /avr_gra/isp10pin.gif 468 0.83
25 /avr_gra/isp6pin.gif 466 0.83
Sum 56,165 100.00

To top of page

Top 25 of 174 entry pages , sorted by number of files

N entry pages times %


1 /index.html 791 16.61
2 /avr_en/index.html 505 10.60
3 /avr_de/index.html 355 7.45
4 /avr_en/beginner/index.html 234 4.91
5 /avr_en/AVR_DAC.html 164 3.44
6 /avr_de/beginner/index.html 137 2.88
7 /avr_de/stepper/stepper.html 104 2.18
8 /avr_de/fcount/fcount_m8.html 89 1.87
9 /avr_de/avr_dac.html 84 1.76
10 /avr_en/beginner/HARDWARE.html 76 1.60
11 /avr_de/keypad/keyboard.html 73 1.53
/avr_de/rechteckgen/rectgen_m8.
12 69 1.45
html
13 /avr_en/keypad/keyboard.html 68 1.43
14 /avr_de/beginner/hardware.html 66 1.39
15 /avr_en/AVR_ADC500.html 58 1.22
16 /avr_en/signalgen/rectgen_m8.html 58 1.22
17 /gb_new.html 50 1.05
18 /avr_de/intro/index.html 48 1.01
19 /avr_de/avr_adc500.html 43 0.90
20 /avr_de/rechnen/konversion.html 42 0.88
21 /avr_de/beginner/ports.html 42 0.88
22 /avr_de/rechnen/multiplikation.html 42 0.88
23 /avr_en/beginner/REGISTER.html 40 0.84
24 /avr_de/beginner/rechnen.html 40 0.84
25 /avr_de/beginner/sprung.html 39 0.82
Sum 4,763 100.00

To top of page

Top 25 of 207 cheat pages , sorted by number of files

N cheat pages times %


1 907 14.78
2 /index.html 482 7.86
3 /avr_en/index.html 411 6.70
4 /avr_de/index.html 326 5.31
5 /avr_en/AVR_DAC.html 174 2.84
6 /avr_en/beginner/RIGHT.html 144 2.35
7 /avr_en/beginner/HARDWARE.html 124 2.02
8 /avr_de/stepper/stepper.html 105 1.71
9 /avr_en/keypad/keyboard.html 101 1.65
10 /avr_de/fcount/fcount_m8.html 95 1.55
11 /avr_de/avr_dac.html 92 1.50
12 /avr_de/keypad/keyboard.html 90 1.47
13 /avr_de/beginner/rechts.html 85 1.39
14 /avr_de/beginner/hardware.html 84 1.37
15 /avr_en/beginner/REGISTER.html 73 1.19
16 /avr_de/beginner/sprung.html 69 1.12
17 /avr_en/beginner/SRAM.html 68 1.11
18 /avr_en/beginner/JUMP.html 65 1.06
19 /avr_en/AVR_ADC500.html 58 0.95
/avr_de/rechteckgen/rectgen_m8.
20 58 0.95
html
21 /avr_de/beginner/rechnen.html 58 0.95
22 /avr_de/beginner/register.html 57 0.93
23 /akkuload/de/index.html 57 0.93
24 /avr_en/signalgen/rectgen_m8.html 52 0.85
25 /avr_de/praesentation/index.html 50 0.81
Sum 6,136 100.00

To top of page

Top 25 of 170 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,568 14.70
2 /avr_en/beginner/index.html 1,178 11.04
3 /avr_de/beginner/index.html 867 8.13
4 / 858 8.04
5 /avr_en/index.html 659 6.18
6 /avr_en/ 632 5.92
7 /avr_en/beginner/RIGHT.html 566 5.31
8 /avr_de/beginner/rechts.html 497 4.66
9 /avr_en/beginner/LEFT.html 442 4.14
10 /avr_de/beginner/links.html 336 3.15
11 /sitemap_de.html 298 2.79
12 /sitemap_en.html 193 1.81
13 /avr_de/interrupts/index.html 165 1.55
14 /avr_de/apps.html 163 1.53
15 /index.html 143 1.34
16 /avr_de/avr_tut.html 107 1.00
17 /avr_de/zeitschleifen/index.html 101 0.95
18 /avr_en/AVR_TUT.html 93 0.87
19 /avr_de/beginner/commands.html 92 0.86
20 /avr_en/calc/index.html 79 0.74
21 /avr_de/rechnen/index.html 72 0.67
22 /avr_en/APPS.html 67 0.63
23 /weblox_en/index.html 67 0.63
24 /weblox_de/index.html 66 0.62
/avr_en/signalgen/rectgen_m8.
25 58 0.54
html
Sum 10,667 100.00

To top of page

Top 25 of 430 external referrers , sorted by number of files

N external referrers times %


1 - 4,835 80.33
2 http://www.elektroda.pl/rtvforum/viewtopic.php?t=1191671 62 1.03
3 http://www.mikrocontroller.net/articles/AVR 53 0.88
4 http://www.webring.com/hub?ring=avr 31 0.52
5 http://www.dg4fac.de/linksunten.html 28 0.47
6 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 20 0.33
7 http://de.wikipedia.org/wiki/R2R-Netzwerk 18 0.30
http://www.avrfreaks.net/index.php?
8 name=PNphpBB2&file=viewtopic&t=7067 18 0.30
3
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
9 15 0.25
ESC_by1_bz0_bs0.html
10 http://www.dg4fac.de/stechlin/index.html 15 0.25
11 http://www.educypedia.be/electronics/avr.htm 14 0.23
12 http://avr-asm.tripod.com/ 14 0.23
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
13 13 0.22
kurs.htm
14 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 13 0.22
15 http://www.serasidis.gr/link.htm 12 0.20
16 http://www.dg4fac.de/rechtsunten.html 12 0.20
http://electrons.psychogenic.com/modules/arms/art/3/
17 AVRGCCProgrammingG 11 0.18
uide.php
18 http://todopic.mforos.com/551641/4566219-grabador-para-atmel/ 11 0.18
19 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 10 0.17
20 http://moodle.concordia.ca/moodle/course/view.php?id=21660 10 0.17
21 http://www.forumseek.net 10 0.17
22 http://www.mikrocontroller.net/topic/31397 9 0.15
23 http://www.mikrocontroller.net/articles/Linksammlung 9 0.15
24 http://www.rowalt.de/mc/avr/linksd.htm 9 0.15
25 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 9 0.15
Sum 6,019 100.00

To top of page

Top 25 of 113 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,598 44.59
2 http://www.google.com 594 16.57
3 http://www.google.at 153 4.27
4 http://www.google.co.in 117 3.26
5 http://www.google.nl 78 2.18
6 http://www.google.ch 71 1.98
7 http://www.google.pl 65 1.81
8 http://www.google.ca 57 1.59
9 http://www.google.co.uk 54 1.51
10 http://www.google.se 42 1.17
11 http://www.google.ro 39 1.09
12 http://www.google.lt 34 0.95
13 http://search.yahoo.com 32 0.89
14 http://www.google.co.id 30 0.84
http://www.google.com.
15 29 0.81
au
http://de.search.yahoo.
16 25 0.70
com
17 http://www.google.fi 23 0.64
18 http://www.google.com.tr 22 0.61
19 http://www.google.it 22 0.61
20 http://www.google.gr 21 0.59
http://www.google.com.
21 21 0.59
pk
22 http://www.google.es 21 0.59
23 http://www.google.hu 21 0.59
24 http://www.google.fr 21 0.59
25 http://www.google.be 20 0.56
Sum 3,584 100.00

To top of page

Top 25 of 2404 search strings , sorted by number of files

N search strings times %


1 avr tutorial 95 2.65
2 avr assembler 59 1.65
3 assembler 47 1.31
4 avr 33 0.92
5 assembler tutorial 27 0.75
6 avr programming 26 0.73
7 attiny13 25 0.70
8 avr codes 24 0.67
9 atmega8 23 0.64
10 avr assembly 22 0.61
11 avr asm 20 0.56
assembler
12 19 0.53
commands
13 AVR tutorial 18 0.50
14 atmel avr 17 0.47
avr assembler
15 17 0.47
tutorial
16 stk500 15 0.42
17 ATtiny13 14 0.39
18 avr asm tutorial 14 0.39
19 AVR 13 0.36
20 Assembler 13 0.36
21 programming avr 11 0.31
22 atmel assembler 10 0.28
23 assembler avr 8 0.22
24 gavrasm 7 0.20
25 r2r dac 7 0.20
Sum 3,584 100.00

To top of page

Top 7 of 7 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 91,897 88.62
2 304 Not changed 10,903 10.51
3 206 Partial information 518 0.50

http://www.avr-asm-tutorial.net/weblox_en/2009w03.html (1 of 2)1/20/2009 8:03:02 PM


Weblog statistic for http://www.avr-asm-tutorial.net

4 301 Permanently moved 210 0.20


5 404 File not found 156 0.15
6 403 Forbidden 8 0.01
7 300 Multiple choices 7 0.01
Sum 103,699 100.00

To top of page

Top 25 of 40 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 61 39.10
2 /beginner_de.pdf 17 10.90
3 /avr_de/intro/ppt/beispiel10_snd.wav 13 8.33
4 /fcount/fcount_m8.html 10 6.41
/_vti_bin/owssvr.dll?
5 7 4.49
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 7 4.49
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
7 /_vti_inf.html 4 2.56
8 /avr_en/source/PWGSIO2.asm 2 1.28
9 /avr_gra/stk_ram.jpg 2 1.28
10 /avr_en/calc/HARDMULT.html 2 1.28
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
11 20la 2 1.28
nguage_files/LEFT.htm
12 /avr_en/beginner/PORT_files/LEFT.htm 1 0.64
13 /avr_en/beginner/PORT_files/RIGHT.htm 1 0.64
/avr_de/beginner/ports.html//footer.inc.php?_AMLconfig[cfg_serverpath]
14 1 0.64
=http://picassocity.com/board//r0x.txt???
//footer.inc.php?_AMLconfig[cfg_serverpath]=http://picassocity.com/boa
15 1 0.64
rd//r0x.txt???
/avr_de/beginner//footer.inc.php?_AMLconfig[cfg_serverpath]=http://pic
16 1 0.64
associty.com/board//r0x.txt???
/avr_de/beginner/errors.php?error=http://cbmarketer.com/images/t_pane.
17 1 0.64
jpg/id.txt??
18 /errors.php?error=http://cbmarketer.com/images/t_pane.jpg/id.txt?? 1 0.64
/avr_de/errors.php?error=http://cbmarketer.com/images/t_pane.jpg/id.tx
19 1 0.64
t??
20 /community/index.html 1 0.64
21 /forums/index.html 1 0.64
22 /forum/index.html 1 0.64
23 /vbulletin/index.html 1 0.64
24 /board/index.html 1 0.64
25 /phpbb/index.html 1 0.64
Sum 156 100.00

To top of page

Top 25 of 117 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 54,375 52.44
2 Mozilla/4.0 38,714 37.33
3 Opera/9.63 2,658 2.56
4 Mozilla/4.5 1,248 1.20
5 Opera/9.62 1,102 1.06
6 msnbot-media/1.1 751 0.72
7 Googlebot-Image/1.0 570 0.55
8 Yanga 515 0.50
9 Xaldon 331 0.32
10 Opera/10.00 311 0.30
11 Opera/9.52 276 0.27
12 msnbot/1.1 268 0.26
13 Opera/9.51 255 0.25
14 Opera/9.24 208 0.20
15 Opera/9.60 184 0.18
16 Opera/9.25 165 0.16
17 Opera/9.61 149 0.14
18 Opera/9.50 125 0.12
19 SapphireWebCrawler/1.0 125 0.12
20 Opera/9.02 124 0.12
SapphireWebCrawler/Nutch-1.0-
21 114 0.11
dev
22 Opera/7.03 92 0.09
23 Opera/9.26 88 0.08
24 - 79 0.08
25 Opera/9.21 79 0.08
Sum 103,699 100.00

To top of page

Top 25 of 285 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 30,691 29.60
2 MSIE 7.0 21,125 20.37
3 MSIE 6.0 13,835 13.34
4 Firefox/3.0.5 3,175 3.06
5 Gecko 2,833 2.73
6 Opera/9.63 2,607 2.51
7 Firefox/2.0.0.20 1,848 1.78
8 Firefox/3.0.3 1,691 1.63
9 Firefox/3.0.4 1,690 1.63
10 FDM 1,606 1.55
11 Firefox/3.0.1 1,508 1.45
12 HTTrack 3.0x 1,248 1.20
13 Slurp 1,149 1.11
14 unknown 1,118 1.08
15 Opera/9.62 1,102 1.06
16 msnbot-media/1.1 751 0.72
17 Firefox/2.0.0.18 650 0.63
Googlebot-
18 570 0.55
Image/1.0
19 Firefox/3.0 503 0.49
20 MSIE 8.0 419 0.40
21 Firefox/2.0.0.11 383 0.37
22 Googlebot/2.1 382 0.37
23 Slurp/3.0 374 0.36
24 WebSpider 2.7.b6 331 0.32
25 Opera/10.00 311 0.30
Sum 103,699 100.00

To top of page

Top 25 of 46 operating systems , sorted by number of files

N operating systems times %


1 Windows 42,765 41.24
2 Windows NT 5.1 35,204 33.95
3 Linux i686 6,823 6.58
4 unknown 5,788 5.58
5 Windows NT 6.0 5,231 5.04
6 Windows NT 5.0 1,744 1.68
7 Windows 98 1,559 1.50
8 Linux x86_64 1,020 0.98
9 Mac OS X 10_5_6 720 0.69
10 Mac OS X 10.5 562 0.54
11 Windows NT 5.2 480 0.46
12 Mac OS X 281 0.27
13 Windows NT 4.0 242 0.23
14 Windows XP 5.1 224 0.22
15 Linux 187 0.18
16 Linux i586 119 0.11
17 Linux i686 111 0.11
18 Windows NT 6.1 103 0.10
19 Mac OS X 10_5_5 100 0.10
20 Windows CE 89 0.09
21 Mac OS X Mach-O 53 0.05
Mac OS X
22 40 0.04
10_4_11
23 Mac OS X 10.4 37 0.04
24 Windows 6.0 33 0.03
25 Win16 30 0.03
Sum 103,699 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 3,064 2.95
2 01 2,115 2.04
3 02 1,487 1.43
4 03 1,664 1.60
5 04 2,109 2.03
6 05 1,470 1.42
7 06 2,087 2.01
8 07 2,376 2.29
9 08 3,424 3.30
10 09 4,229 4.08
11 10 4,638 4.47
12 11 5,667 5.46
13 12 6,819 6.58
14 13 5,676 5.47
15 14 5,772 5.57
16 15 6,487 6.26
17 16 7,469 7.20
18 17 5,453 5.26
19 18 5,921 5.71
20 19 5,720 5.52
21 20 5,911 5.70
22 21 6,011 5.80
23 22 4,493 4.33
24 23 3,637 3.51
Sum 103,699 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2009w03.html (2 of 2)1/20/2009 8:03:02 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2009w02

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2009 , week 02

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5637 IPs and host names , sorted by number of files

N IPs and host names times %


1 41.201.123.244=(not found) 1,280 1.36
2 67.195.37.111=llf320022.crawl.yahoo.net 416 0.44
3 84.146.240.138=p5492F08A.dip.t-dialin.net 375 0.40
4 217.85.203.141=pD955CB8D.dip.t-dialin.net 354 0.38
5 72.30.87.112=llf531192.crawl.yahoo.net 347 0.37
6 66.249.71.207=crawl-66-249-71-207.googlebot.com 338 0.36
7 79.193.117.235=p4FC175EB.dip.t-dialin.net 327 0.35
8 91.180.109.162=162.109-180-91.adsl-dyn.isp.belgacom.be 325 0.35
9 66.249.71.205=crawl-66-249-71-205.googlebot.com 313 0.33
10 66.249.71.206=crawl-66-249-71-206.googlebot.com 301 0.32
11 193.27.113.219=(not found) 285 0.30
122.164.191.26=ABTS-TN-dynamic-026.191.164.122.airtelbroadband.
12 220 0.23
in
13 192.33.126.163=(not found) 212 0.23
14 81.63.137.33=33-137.63-81.stat.fixnetdata.ch 212 0.23
15 217.232.83.20=pD9E85314.dip.t-dialin.net 209 0.22
16 89.61.194.44=Zc22c.z.pppool.de 193 0.21
17 222.124.203.54=(not found) 191 0.20
18 217.228.210.223=pD9E4D2DF.dip.t-dialin.net 171 0.18
19 89.61.147.253=Z93fd.z.pppool.de 170 0.18
20 81.225.101.240=h240n6c1o1052.bredband.skanova.com 169 0.18
21 62.168.101.197=197.dudic.sv.gtsi.sk 160 0.17
22 80.131.181.93=p5083B55D.dip0.t-ipconnect.de 155 0.16
23 67.195.37.164=llf320062.crawl.yahoo.net 151 0.16
24 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 150 0.16
25 80.228.67.101=dynadsl-080-228-67-101.ewetel.net 146 0.16
Sum 94,077 100.00

To top of page

Top 25 of 5637 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 41.201.123.244=(not found) 19,455 1.81
2 89.61.194.44=Zc22c.z.pppool.de 12,313 1.15
3 91.22.201.213=p5B16C9D5.dip.t-dialin.net 9,718 0.91
4 72.30.87.112=llf531192.crawl.yahoo.net 9,182 0.86
5 84.146.240.138=p5492F08A.dip.t-dialin.net 8,416 0.78
6 217.85.203.141=pD955CB8D.dip.t-dialin.net 8,088 0.75
7 87.152.175.189=p5798AFBD.dip.t-dialin.net 7,289 0.68
8 79.193.117.235=p4FC175EB.dip.t-dialin.net 6,735 0.63
9 84.132.241.112=p5484F170.dip.t-dialin.net 6,138 0.57
10 84.185.103.235=p54B967EB.dip.t-dialin.net 5,867 0.55
11 87.162.180.168=p57A2B4A8.dip.t-dialin.net 5,864 0.55
12 217.232.83.20=pD9E85314.dip.t-dialin.net 5,680 0.53
13 212.77.163.104=(not found) 5,570 0.52
14 77.22.163.253=(not found) 5,359 0.50
15 67.195.37.111=llf320022.crawl.yahoo.net 5,303 0.49
16 79.219.199.18=p4FDBC712.dip0.t-ipconnect.de 5,135 0.48
17 217.115.75.230=proxy2-nsn.nsn-inter.net 5,079 0.47
18 78.52.112.199=(not found) 5,045 0.47
19 217.16.162.131=(not found) 4,614 0.43
20 66.249.71.207=crawl-66-249-71-207.googlebot.com 4,439 0.41
21 217.235.253.28=pD9EBFD1C.dip.t-dialin.net 4,311 0.40
22 195.243.67.149=(not found) 4,303 0.40
23 93.132.166.109=stgt-5d84a66d.pool.einsundeins.de 4,240 0.39
24 134.130.15.1=orthanc.klinikum.RWTH-Aachen.DE 4,137 0.39
88.77.252.240=dslb-088-077-252-240.pools.arcor-ip.
25 4,135 0.39
net
Sum 1,073,579 100.00

To top of page

Top 25 of 908 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.206=crawl-66-249-71-206.googlebot.com 98 2.78
2 67.195.37.111=llf320022.crawl.yahoo.net 82 2.33
3 66.249.71.207=crawl-66-249-71-207.googlebot.com 82 2.33
4 66.249.71.205=crawl-66-249-71-205.googlebot.com 75 2.13
5 72.30.87.112=llf531192.crawl.yahoo.net 68 1.93
6 58.148.8.37=(not found) 53 1.51
7 67.195.37.164=llf320062.crawl.yahoo.net 45 1.28
8 84.247.45.83=(not found) 41 1.17
9 193.252.149.15=natcrawlbloc02.net.s1.fti.net 32 0.91
10 81.52.143.16=natcrawlbloc03.net.m1.fti.net 32 0.91
11 81.52.143.15=natcrawlbloc01.net.m1.fti.net 31 0.88
12 212.143.177.197=(not found) 31 0.88
13 88.131.106.16=(not found) 27 0.77
14 81.52.143.26=natcrawlbloc05.net.m1.fti.net 27 0.77
15 193.47.80.44=crawl08.exabot.com 25 0.71
16 72.30.87.94=llf531170.crawl.yahoo.net 24 0.68
17 123.118.13.126=(not found) 19 0.54
18 74.6.8.125=llf520032.crawl.yahoo.net 18 0.51
19 208.115.111.244=crawl3.dotnetdotcom.org 18 0.51
20 193.252.149.16=natcrawlbloc04.net.s1.fti.net 18 0.51
21 67.195.37.157=llf320058.crawl.yahoo.net 17 0.48
65.55.209.159=msnbot-65-55-209-159.search.msn.
22 16 0.45
com
23 203.209.252.66=hd901036.inktomisearch.com 16 0.45
65.55.209.167=msnbot-65-55-209-167.search.msn.
24 15 0.43
com
65.55.209.158=msnbot-65-55-209-158.search.msn.
25 15 0.43
com
Sum 3,519 100.00

To top of page

Top 25 of 92 countries of origin , sorted by number of files

N countries of origin times %


1 net 28,229 30.01
2 Germany 21,072 22.40
3 (unresolved) 16,929 17.99
4 com 5,508 5.85
5 Poland 2,476 2.63
6 Austria 2,043 2.17
7 Switzerland 1,639 1.74
8 India 1,211 1.29
9 Netherlands 1,025 1.09
10 Indonesia 837 0.89
11 Italy 830 0.88
12 Belgium 827 0.88
13 Greece 655 0.70
14 Hungary 632 0.67
15 Czech Republic 616 0.65
16 Romania 578 0.61
17 Slovak Republic 553 0.59
18 Australia 519 0.55
19 United Kingdom 515 0.55
20 Canada 470 0.50
21 Brazil 438 0.47
22 Lithuania 436 0.46
23 Mexico 418 0.44
24 Sweden 400 0.43
25 France 347 0.37
Sum 94,077 100.00

To top of page

Top 25 of 138 pathes , sorted by number of files

N pathes times %
1 /common/ 32,795 34.86
2 /avr_gra/ 18,307 19.46
3 / 10,923 11.61
4 /avr_en/beginner/ 3,785 4.02
5 /avr_de/beginner/ 3,043 3.23
6 /avr_de/ 2,784 2.96
7 /avr_en/ 2,424 2.58
8 /avr_de/rechnen/ 1,706 1.81
9 /avr_de/fcount/ 1,678 1.78
10 /avr_en/calc/ 1,365 1.45
11 /avr_de/stepper/ 1,267 1.35
12 /avr_de/praesentation/ 1,201 1.28
13 /avr_de/quellen/ 864 0.92
14 /avr_en/source/ 842 0.90
/avr_de/rechteckgen/
15 821 0.87
bilder/
16 /avr_en/keypad/ 773 0.82
17 /avr_de/keypad/ 761 0.81
18 /avr_en/signalgen/pics/ 702 0.75
19 /gavrasm/ 663 0.70
20 /avr_de/zeitschleifen/ 591 0.63
21 /avr_de/interrupts/ 519 0.55
22 /avr_en/stepper/ 413 0.44
23 /akkuload/ 350 0.37
24 /gavrasm/v22/ 326 0.35
25 /avr_en/signalgen/ 285 0.30
Sum 94,077 100.00

To top of page

Top 25 of 138 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 205,600 19.15
2 /avr_gra/ 198,102 18.45
3 /avr_de/intro/pdf/ 93,085 8.67
4 /avr_de/fcount/ 65,266 6.08
5 / 63,207 5.89
6 /avr_de/ 46,812 4.36
7 /avr_en/ 36,017 3.35
8 /avr_de/stepper/ 35,075 3.27
9 /gavrasm/v22/ 31,092 2.90
10 /avr_en/beginner/ 30,454 2.84
11 /avr_de/beginner/ 29,302 2.73
/avr_de/rechteckgen/
12 20,177 1.88
bilder/
13 /avr_en/signalgen/pics/ 18,911 1.76
14 /avr_de/rechnen/ 16,182 1.51
15 /common/ 15,922 1.48
16 /avr_en/calc/ 11,667 1.09
17 /privat/magloop/ 11,569 1.08
18 /avr_de/intro/ppt/ 11,536 1.07
19 /avr_de/rechteckgen/ 11,471 1.07
20 /avr_en/signalgen/ 10,738 1.00
21 /avr_en/stepper/ 9,690 0.90
22 /akkuload/ 9,296 0.87
23 /avr_en/fcount/ 8,039 0.75
24 /avr_en/keypad/ 5,952 0.55
25 /avr_de/interrupts/ 5,868 0.55
Sum 1,073,579 100.00

To top of page

Top 25 of 1430 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 5,026 5.34
2 /avr_gra/RingLogo.jpg 2,557 2.72
/common/knowhow.
3 2,120 2.25
gif
4 /common/clock.gif 2,118 2.25
/common/download.
5 2,118 2.25
gif
6 /common/app.gif 2,117 2.25
7 /common/akkuload.gif 2,116 2.25
8 /common/gavrasm.gif 2,106 2.24
/common/gavrasmw.
9 2,101 2.23
gif
10 /common/adc.gif 2,100 2.23
11 /common/hardware.gif 2,097 2.23
12 /common/example.gif 2,095 2.23
13 /common/calc.gif 2,095 2.23
14 /common/keyb.gif 2,095 2.23
15 /common/r2r.gif 2,093 2.22
16 /avr_gra/stk_lcd.jpg 2,090 2.22
17 /common/beginner.gif 2,087 2.22
18 /index.html 1,509 1.60
19 /avr_de/index.html 1,253 1.33
20 /avr_en/index.html 1,192 1.27
21 /avr_2313.gif 1,164 1.24
22 /dg4fac.gif 1,164 1.24
23 /avr-asm-tutorial.gif 1,160 1.23
24 /common/ints.gif 1,114 1.18
25 /common/delay.gif 1,112 1.18
Sum 94,077 100.00

To top of page

Top 25 of 1430 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 72,320 6.74
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 45,530 4.24
3 /avr_de/index.html 29,907 2.79
4 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 25,514 2.38
5 /avr_en/index.html 25,282 2.35
6 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 24,885 2.32
/avr_de/praesentation/Teil_5b_Beispiel01_02.
7 24,013 2.24
pdf
8 /avr_2313.gif 21,020 1.96
9 /avr_gra/tn13_exp.jpg 20,647 1.92
10 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 16,735 1.56
11 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 13,792 1.28
12 /avr_de/fcount/dscf0004.jpg 12,610 1.17
13 /dg4fac.gif 12,595 1.17
14 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 11,857 1.10
15 /avr_de/fcount/dscf0005.jpg 11,132 1.04
16 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 10,844 1.01
17 /avr_de/fcount/dscf0001.jpg 10,579 0.99
18 /avr_gra/pwm_simul.jpg 10,325 0.96
19 /gavrasm/v22/gavrasm_win_de_22.zip 10,298 0.96
20 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 10,019 0.93
21 /favicon.ico 9,896 0.92
22 /avr_gra/r2r_hardware.jpg 9,710 0.90
23 /avr_gra/tn13_exp.gif 9,431 0.88
24 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 9,324 0.87
25 /avr_en/signalgen/pics/rectgen_wiring.jpg 8,696 0.81
Sum 1,073,579 100.00

To top of page

Top 25 of 270 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,509 7.95
2 /avr_de/index.html 1,253 6.60
3 /avr_en/index.html 1,192 6.28
4 /avr_en/beginner/LEFT.html 893 4.71
5 /avr_en/beginner/index.html 598 3.15
6 /avr_en/beginner/RIGHT.html 586 3.09
7 /avr_de/beginner/index.html 478 2.52
8 /avr_de/beginner/links.html 472 2.49
9 /avr_de/beginner/rechts.html 435 2.29
/avr_en/beginner/HARDWARE.
10 280 1.48
html
11 /avr_de/beginner/hardware.html 234 1.23
12 /avr_en/beginner/REGISTER.html 198 1.04
13 /avr_en/AVR_DAC.html 184 0.97
14 /avr_de/stepper/stepper.html 180 0.95
15 /avr_de/beginner/register.html 179 0.94
16 /avr_de/beginner/sprung.html 178 0.94
17 /avr_de/praesentation/index.html 174 0.92
18 /avr_en/keypad/keyboard.html 166 0.87
19 /avr_en/beginner/JUMP.html 164 0.86
20 /avr_de/keypad/keyboard.html 158 0.83
21 /avr_en/beginner/PORTS.html 155 0.82
22 /avr_de/beginner/ports.html 149 0.79
23 /avr_de/fcount/fcount_m8.html 148 0.78
24 /avr_de/apps.html 144 0.76
25 /avr_en/beginner/TOOLS.html 144 0.76
Sum 18,972 100.00

To top of page

Top 25 of 270 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 29,907 14.01
2 /avr_en/index.html 25,282 11.85
3 /index.html 8,100 3.80
4 /avr_de/dcf77uhr.html 5,022 2.35
5 /gb_new.html 4,836 2.27
6 /avr_de/beginner/sprung.html 4,619 2.16
7 /avr_en/beginner/RIGHT.html 4,288 2.01
8 /avr_en/beginner/JUMP.html 3,978 1.86
9 /avr_en/keypad/keyboard.html 3,520 1.65
10 /avr_en/beginner/CALC.html 3,276 1.54
11 /avr_de/keypad/keyboard.html 3,190 1.49
12 /avr_de/beginner/rechts.html 3,040 1.42
13 /avr_de/stepper/stepper.html 2,800 1.31
14 /avr_en/beginner/LEFT.html 2,725 1.28
15 /avr_en/AVR_DAC.html 2,677 1.25
16 /avr_de/beginner/rechnen.html 2,646 1.24
17 /avr_de/beginner/pdetail.html 2,626 1.23
/avr_de/rechteckgen/rectgen_m8.
18 2,548 1.19
html
19 /avr_de/beginner/hardware.html 2,409 1.13
20 /sitemap_de.html 2,400 1.12
21 /avr_en/beginner/REGISTER.html 2,381 1.12
22 /avr_en/beginner/HARDWARE.html 2,367 1.11
/avr_en/beginner/COMMANDS.
23 2,332 1.09
html
24 /avr_en/signalgen/rectgen_m8.html 2,331 1.09
25 /avr_de/beginner/ports.html 2,119 0.99
Sum 213,397 100.00

To top of page

Top 25 of 429 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,557 18.12
2 /avr_gra/stk_lcd.jpg 2,090 14.81
3 /avr_gra/exp2313g.jpg 496 3.52
4 /avr_gra/8515.jpg 474 3.36
5 /avr_gra/tn13_exp.jpg 474 3.36
6 /avr_gra/avr_isp.jpg 471 3.34
7 /avr_gra/exp_2313.jpg 469 3.32
8 /avr_gra/r2r_wave.jpg 321 2.27
9 /avr_gra/r2r_sawtooth.jpg 289 2.05
10 /avr_gra/r2r_hardware.jpg 272 1.93
11 /avr_gra/r2r_sawtoothupperbound.jpg 269 1.91
12 /avr_gra/r2r_triangle.jpg 268 1.90
13 /avr_gra/r2r_sawtooth741.jpg 267 1.89
14 /avr_gra/r2r_upperbound.jpg 266 1.89
15 /avr_gra/AT90S8515.jpg 232 1.64
16 /avr_gra/apps.jpg 193 1.37
17 /avr_gra/adc8conn.jpg 183 1.30
18 /avr_gra/pwm_simul.jpg 182 1.29
19 /avr_de/stepper/stepper_sm.jpg 181 1.28
20 /avr_de/stepper/supply.jpg 173 1.23
21 /avr_de/stepper/kp4m4-001.jpg 171 1.21
22 /akkuload/dscf0030s.jpg 169 1.20
23 /avr_de/stepper/driver.jpg 167 1.18
24 /avr_de/praesentation/zuendtester.jpg 165 1.17
/avr_de/rechteckgen/bilder/rectgen_280.
25 160 1.13
jpg
Sum 14,110 100.00

To top of page

Top 25 of 389 GIF-files , sorted by number of files

N GIF-files times %
/common/knowhow.
1 2,120 4.14
gif
2 /common/clock.gif 2,118 4.13
3 /common/app.gif 2,117 4.13
/common/download.
4 2,117 4.13
gif
5 /common/akkuload.gif 2,116 4.13
6 /common/gavrasm.gif 2,106 4.11
/common/gavrasmw.
7 2,101 4.10
gif
8 /common/adc.gif 2,100 4.10
9 /common/hardware.gif 2,097 4.09
10 /common/example.gif 2,095 4.09
11 /common/calc.gif 2,095 4.09
12 /common/keyb.gif 2,095 4.09
13 /common/r2r.gif 2,093 4.09
14 /common/beginner.gif 2,087 4.07
15 /avr_2313.gif 1,164 2.27
16 /dg4fac.gif 1,164 2.27
17 /avr-asm-tutorial.gif 1,160 2.26
18 /common/ints.gif 1,114 2.17
19 /common/delay.gif 1,112 2.17
20 /common/tn13.gif 1,111 2.17
21 /avr_gra/2313.gif 1,003 1.96
22 /avr_gra/exp2313.gif 472 0.92
23 /avr_gra/isp6pin.gif 470 0.92
24 /avr_gra/avr_isp.gif 470 0.92
25 /avr_gra/tn13_exp.gif 470 0.92
Sum 51,227 100.00

To top of page

Top 25 of 176 entry pages , sorted by number of files

N entry pages times %


1 /index.html 772 17.51
2 /avr_en/index.html 445 10.10
3 /avr_de/index.html 371 8.42
4 /avr_en/beginner/index.html 202 4.58
5 /avr_en/AVR_DAC.html 121 2.75
6 /avr_de/stepper/stepper.html 109 2.47
7 /avr_de/beginner/index.html 100 2.27
8 /avr_en/beginner/HARDWARE.html 94 2.13
9 /avr_de/fcount/fcount_m8.html 88 2.00
10 /avr_de/beginner/hardware.html 77 1.75
11 /avr_de/avr_dac.html 74 1.68
12 /avr_en/keypad/keyboard.html 72 1.63
13 /avr_de/keypad/keyboard.html 69 1.57
/avr_de/rechteckgen/rectgen_m8.
14 62 1.41
html
15 /avr_en/signalgen/rectgen_m8.html 61 1.38
16 /avr_de/intro/index.html 55 1.25
17 /privat/stechlin/index.html 54 1.23
18 /gb_new.html 53 1.20
19 /avr_de/rechnen/konversion.html 49 1.11
20 /avr_en/AVR_ADC500.html 46 1.04
/avr_en/beginner/COMMANDS.
21 42 0.95
html
22 /avr_de/avr_adc500.html 41 0.93
23 /avr_de/beginner/pdetail.html 37 0.84
24 /avr_de/beginner/diraus.html 35 0.79
25 /avr_en/calc/CONVERSION.html 32 0.73
Sum 4,408 100.00

To top of page

Top 25 of 197 cheat pages , sorted by number of files

N cheat pages times %


1 799 14.17
2 /index.html 439 7.79
3 /avr_en/index.html 374 6.63
4 /avr_de/index.html 322 5.71
5 /avr_en/AVR_DAC.html 129 2.29
6 /avr_en/beginner/HARDWARE.html 117 2.08
7 /avr_en/beginner/RIGHT.html 111 1.97
8 /avr_de/stepper/stepper.html 105 1.86
9 /avr_de/beginner/hardware.html 93 1.65
10 /avr_en/keypad/keyboard.html 84 1.49
11 /avr_de/keypad/keyboard.html 81 1.44
12 /avr_de/fcount/fcount_m8.html 78 1.38
13 /avr_de/avr_dac.html 70 1.24
14 /avr_de/beginner/rechts.html 65 1.15
15 /avr_en/beginner/REGISTER.html 62 1.10
/avr_de/rechteckgen/rectgen_m8.
16 60 1.06
html
17 /avr_de/praesentation/index.html 59 1.05
18 /akkuload/de/index.html 56 0.99
19 /avr_en/AVR_ADC500.html 56 0.99
20 /avr_de/avr_adc500.html 53 0.94
21 /privat/stechlin/index.html 53 0.94
22 /gb_new.html 52 0.92
23 /avr_en/beginner/CALC.html 52 0.92
24 /avr_en/beginner/JUMP.html 52 0.92
25 /avr_en/signalgen/rectgen_m8.html 50 0.89
Sum 5,637 100.00

To top of page

Top 25 of 165 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,618 16.38
2 /avr_en/beginner/index.html 1,357 13.74
3 /avr_de/beginner/index.html 802 8.12
4 / 651 6.59
5 /avr_en/index.html 547 5.54
6 /avr_en/beginner/RIGHT.html 527 5.34
7 /avr_de/beginner/rechts.html 513 5.19
8 /avr_en/ 425 4.30
9 /avr_en/beginner/LEFT.html 361 3.65
10 /sitemap_en.html 252 2.55
11 /avr_de/beginner/links.html 250 2.53
12 /sitemap_de.html 232 2.35
13 /index.html 211 2.14
14 /avr_de/apps.html 173 1.75
15 /avr_de/interrupts/index.html 150 1.52
16 /avr_de/avr_tut.html 130 1.32
17 /avr_de/ 128 1.30
18 /avr_de/zeitschleifen/index.html 127 1.29
19 /avr_en/calc/index.html 95 0.96
20 /avr_en/AVR_TUT.html 67 0.68
21 /avr_en/APPS.html 66 0.67
22 /avr_de/rechnen/index.html 58 0.59
23 /avr_en/signalgen/rectgen_m8.html 58 0.59
24 /avr_en/calc/CONVERSION.html 47 0.48
/avr_de/rechteckgen/rectgen_m8.
25 41 0.42
html
Sum 9,878 100.00

To top of page

Top 25 of 412 external referrers , sorted by number of files

N external referrers times %


1 - 4,531 80.77
2 http://www.mikrocontroller.net/articles/AVR 47 0.84
3 http://www.webring.com/hub?ring=avr 43 0.77
4 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 25 0.45
5 http://www.dg4fac.de/linksunten.html 22 0.39
6 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 21 0.37
7 http://www.elektroda.pl/rtvforum/viewtopic.php?t=1191671 20 0.36
8 http://de.wikipedia.org/wiki/R2R-Netzwerk 19 0.34
9 http://www.serasidis.gr/link.htm 19 0.34
10 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 18 0.32
11 http://www.dg4fac.de/rechtsunten.html 15 0.27
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
12 15 0.27
kurs.htm
13 http://www.educypedia.be/electronics/avr.htm 14 0.25
14 http://www.mikrocontroller.net/articles/Linksammlung 14 0.25
http://forum.electronicwerkstatt.de/phpBB/
15 topic7388_f28_bxtopic_timexD 14 0.25
ESC_by1_bz0_bs0.html
16 http://frank.bol.ucla.edu/avr.htm 13 0.23
17 http://www.raw.to/rubriken/private_elektronik.html 13 0.23
18 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 12 0.21
19 http://avr-asm.tripod.com/ 11 0.20
20 11 0.20
21 http://www.rowalt.de/mc/avr/linksd.htm 10 0.18
22 http://blackstrom.derschwarz.de/avr/avr/index.shtml 9 0.16
23 http://attiny.com/avrlinks.htm 9 0.16
24 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 8 0.14
http://www.stud.uni-stuttgart.de/studweb/users/etk/etk39219/avrc/index
25 7 0.12
.htm
Sum 5,610 100.00

To top of page

Top 25 of 124 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,535 47.14
2 http://www.google.com 501 15.39
3 http://www.google.at 102 3.13
4 http://www.google.co.in 101 3.10
5 http://www.google.nl 79 2.43
6 http://www.google.ch 70 2.15
7 http://www.google.pl 66 2.03
8 http://www.google.co.uk 58 1.78
9 http://www.google.ro 41 1.26
10 http://www.google.ca 39 1.20
http://www.google.com.
11 34 1.04
au
12 http://www.google.se 32 0.98
13 http://www.google.be 27 0.83
14 http://www.google.co.id 25 0.77
15 http://www.google.fi 24 0.74
http://www.google.com.
16 21 0.64
vn
17 http://www.google.it 21 0.64
18 http://www.google.fr 21 0.64
19 http://www.google.sk 18 0.55
20 http://www.google.hu 18 0.55
21 http://search.yahoo.com 16 0.49
22 http://www.google.gr 16 0.49
http://www.google.com.
23 16 0.49
pk
24 http://www.google.com.tr 14 0.43
25 http://search.live.com 14 0.43
Sum 3,256 100.00

To top of page

Top 25 of 2165 search strings , sorted by number of files

N search strings times %


1 avr tutorial 94 2.89
2 avr assembler 70 2.15
3 avr 55 1.69
4 avr programming 33 1.01
5 attiny13 32 0.98
6 assembler 26 0.80
assembler
7 25 0.77
commands
8 avr assembly 15 0.46
9 avr asm tutorial 15 0.46
10 AVR 15 0.46
11 AVR tutorial 12 0.37
12 atmel assembler 12 0.37
avr assembler
13 12 0.37
tutorial
14 avr asm 12 0.37
15 assembler tutorial 11 0.34
16 atmega8 11 0.34
17 assembler lernen 10 0.31
18 atmega tutorial 10 0.31
19 ATtiny13 10 0.31
20 atmel avr 10 0.31
21 AVR Assembler 9 0.28
22 AVR programming 9 0.28
23 katomic 9 0.28
24 gavrasm 9 0.28
25 r2r network 8 0.25
Sum 3,256 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 84,682 90.01
2 304 Not changed 8,495 9.03
3 206 Partial information 532 0.57
4 301 Permanently moved 210 0.22
5 404 File not found 117 0.12

http://www.avr-asm-tutorial.net/weblox_en/2009w02.html (1 of 2)1/20/2009 8:03:23 PM


Weblog statistic for http://www.avr-asm-tutorial.net

6 403 Forbidden 22 0.02


7 300 Multiple choices 10 0.01
8 xxx Unknown error 7 0.01
9 xxx Unknown error 2 0.00
Sum 94,077 100.00

To top of page

Top 25 of 55 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 34 29.06
2 /beginner_de.pdf 14 11.97
3 /hostnamehttp://www.poliauto.ca//media/test.txt?? 6 5.13
/_vti_bin/owssvr.dll?
4 3 2.56
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
5 3 2.56
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
6 20la 3 2.56
nguage_files/LEFT.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
7 20AVR-Assemble 2 1.71
r-Dateien/links.htm
8 /avr_de/keypad/gb_new.html 2 1.71
9 /keypad/gb_new.html 2 1.71
10 /avr_de/praesentation/favicon.ico 2 1.71
11 /avr_de/praesentation/favicon.gif 2 1.71
12 /sitemap.xml 1 0.85
//components/com_simpleboard/file_upload.php?sbp=http://www.alternativ
13 1 0.85
esud.com/ressources/cms/modules/.../sistem.txt???
/_vti_bin/owssvr.dll?
14 1 0.85
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
15 1 0.85
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
16 /en/index.html 1 0.85
17 /avr/de/index.html 1 0.85
/_vti_bin/owssvr.dll?
18 1 0.85
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
19 1 0.85
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
20 /http://www.shinedruk.pl/assets/images/test.txt??? 1 0.85
//components/com_joomlaboard/file_upload.php?sbp=http://www.alternativ
21 1 0.85
esud.com/ressources/cms/modules/.../sistem.txt???
//components/com_minibb/bb_plugins.php?absolute_path=http://www.altern
22 1 0.85
ativesud.com/ressources/cms/modules/.../sistem.txt???
/gb_new.html//main.php?p=http://www.geocities.com/jakautama30/idpit.tx
23 1 0.85
t??
24 //main.php?p=http://www.geocities.com/jakautama30/idpit.txt?? 1 0.85
25 //main.php?p=http://h1.ripway.com/budi212/idpit.txt?? 1 0.85
Sum 117 100.00

To top of page

Top 25 of 115 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 52,477 55.78
2 Mozilla/4.0 31,413 33.39
3 Opera/9.63 3,132 3.33
4 Mozilla/4.5 1,820 1.93
5 Opera/9.62 1,583 1.68
6 Xaldon 331 0.35
7 Opera/9.52 306 0.33
8 msnbot/1.1 268 0.28
Googlebot-
9 267 0.28
Image/1.0
10 Opera/9.24 215 0.23
11 msnbot-media/1.1 210 0.22
12 123345 193 0.21
13 Opera/9.60 186 0.20
14 Opera/9.50 143 0.15
15 Opera/9.51 134 0.14
16 Opera/9.26 120 0.13
17 Opera/10.00 87 0.09
18 Opera/9.25 80 0.09
echobot/echobot-
19 75 0.08
v0.5
20 Opera/9.27 67 0.07
21 Safari5525.27.1 65 0.07
22 Speedy 59 0.06
23 Opera/9.61 59 0.06
24 CFNetwork/221.5 54 0.06
25 Opera/9.12 54 0.06
Sum 94,077 100.00

To top of page

Top 25 of 276 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 29,216 31.06
2 MSIE 7.0 17,046 18.12
3 MSIE 6.0 12,064 12.82
4 Opera/9.63 3,132 3.33
5 Gecko 3,112 3.31
6 Firefox/2.0.0.20 2,400 2.55
7 Firefox/3.0.5 2,378 2.53
8 Firefox/3.0.4 1,941 2.06
9 Firefox/3.0.1 1,825 1.94
10 HTTrack 3.0x 1,818 1.93
11 Opera/9.62 1,520 1.62
12 Slurp 1,183 1.26
13 Firefox/3.0.3 1,174 1.25
14 Firefox/3.0 950 1.01
15 unknown 883 0.94
16 Googlebot/2.1 702 0.75
17 FDM 691 0.73
18 MSIE 8.0 387 0.41
19 Firefox/2.0.0.18 378 0.40
20 Firefox/2.0.0.16 357 0.38
21 WebSpider 2.7.b6 331 0.35
22 Opera/9.52 306 0.33
23 Firefox/2.0.0.14 297 0.32
24 Firefox/3.1b2 285 0.30
25 Slurp/3.0 284 0.30
Sum 94,077 100.00

To top of page

Top 25 of 43 operating systems , sorted by number of files

N operating systems times %


1 Windows 41,292 43.89
2 Windows NT 5.1 28,746 30.56
3 Linux i686 5,947 6.32
4 Windows NT 6.0 5,844 6.21
5 unknown 5,124 5.45
6 Windows 98 2,031 2.16
7 Windows NT 5.0 1,555 1.65
8 Linux x86_64 824 0.88
9 Mac OS X 10_5_6 625 0.66
10 Mac OS X 10.5 420 0.45
11 Linux 292 0.31
Mac OS X
12 245 0.26
10_4_11
13 Mac OS X 238 0.25
14 Windows XP 5.1 234 0.25
15 Windows NT 5.2 196 0.21
16 Mac OS X Mach-O 98 0.10
17 Linux i686 57 0.06
18 Mac OS X 10_5_5 57 0.06
19 Mac OS X 10.4 49 0.05
20 Windows 6.0 46 0.05
21 SunOS i86pc 30 0.03
22 X11 28 0.03
23 Windows CE 19 0.02
24 Windows NT 6.1 18 0.02
25 AmigaOS V53 11 0.01
Sum 94,077 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,743 2.92
2 01 2,310 2.46
3 02 1,625 1.73
4 03 1,330 1.41
5 04 1,628 1.73
6 05 1,437 1.53
7 06 1,690 1.80
8 07 1,731 1.84
9 08 2,731 2.90
10 09 4,316 4.59
11 10 3,768 4.01
12 11 4,688 4.98
13 12 5,802 6.17
14 13 5,348 5.68
15 14 5,604 5.96
16 15 4,844 5.15
17 16 5,224 5.55
18 17 5,846 6.21
19 18 5,370 5.71
20 19 5,379 5.72
21 20 5,960 6.34
22 21 5,273 5.60
23 22 5,292 5.63
24 23 4,138 4.40
Sum 94,077 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2009w02.html (2 of 2)1/20/2009 8:03:23 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2009w01

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2009 , week 01

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 3060 IPs and host names , sorted by number of files

N IPs and host names times %


1 85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.de 874 1.67
2 90.149.187.3=149-187-3.oke2-bras5.adsl.tele2.no 643 1.23
3 91.205.124.9=(not found) 511 0.97
4 72.30.87.112=llf531192.crawl.yahoo.net 361 0.69
5 78.46.86.53=crawl1.hetzner.itroot.de 348 0.66
6 67.195.37.111=llf320022.crawl.yahoo.net 333 0.63
7 87.4.167.221=host221-167-dynamic.4-87-r.retail.telecomitalia.it 253 0.48
8 84.146.42.69=p54922A45.dip0.t-ipconnect.de 248 0.47
9 208.115.111.244=crawl3.dotnetdotcom.org 223 0.42
10 89.60.189.145=Ybd91.y.pppool.de 204 0.39
121.227.152.200=200.152.227.121.broad.sz.js.dynamic.163data.com.
11 198 0.38
cn
12 77.188.229.57=brmn-4dbce539.pool.einsundeins.de 192 0.37
13 83.80.68.140=5350448C.cable.casema.nl 186 0.35
14 84.0.97.62=dsl5400613E.pool.t-online.hu 186 0.35
15 213.39.181.23=c181023.adsl.hansenet.de 168 0.32
16 91.97.102.60=host-091-097-102-060.ewe-ip-backbone.de 149 0.28
17 203.162.3.170=(not found) 148 0.28
18 65.55.217.44=(not found) 142 0.27
19 64.128.171.4=64-128-171-4.static.twtelecom.net 138 0.26
20 66.249.71.206=crawl-66-249-71-206.googlebot.com 134 0.26
21 195.26.23.221=terminal-4-221.retsat1.com.pl 132 0.25
22 79.199.229.181=p4FC7E5B5.dip.t-dialin.net 130 0.25
23 85.225.114.33=c-2172e155.138-2-64736c10.cust.bredbandsbolaget.se 129 0.25
24 88.104.236.124=88-104-236-124.dynamic.dsl.as9105.com 127 0.24
25 92.124.62.215=92-124-62-215.pppoe.irtel.ru 124 0.24
Sum 52,473 100.00

To top of page

Top 25 of 3060 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 85.16.16.201=dyndsl-085-016-016-201.ewe-ip-backbone.de 31,904 5.10
2 91.205.124.9=(not found) 17,322 2.77
3 72.30.87.112=llf531192.crawl.yahoo.net 10,159 1.62
4 80.142.240.222=p508EF0DE.dip.t-dialin.net 7,757 1.24
5 82.82.209.105=dslc-082-082-209-105.pools.arcor-ip.net 6,619 1.06
6 91.12.114.10=p5B0C720A.dip.t-dialin.net 6,218 0.99
7 85.127.135.21=85-127-135-21.dynamic.xdsl-line.inode.at 6,123 0.98
8 79.199.229.181=p4FC7E5B5.dip.t-dialin.net 6,112 0.98
9 90.149.187.3=149-187-3.oke2-bras5.adsl.tele2.no 5,816 0.93
10 91.21.226.166=p5B15E2A6.dip.t-dialin.net 5,043 0.81
11 84.146.42.69=p54922A45.dip0.t-ipconnect.de 5,034 0.80
121.227.152.200=200.152.227.121.broad.sz.js.dynamic.163data.com.
12 5,019 0.80
cn
13 87.167.101.148=p57A76594.dip.t-dialin.net 4,651 0.74
14 67.195.37.111=llf320022.crawl.yahoo.net 4,331 0.69
15 78.46.86.53=crawl1.hetzner.itroot.de 4,312 0.69
16 77.128.49.190=BAA31be.baa.pppool.de 3,789 0.61
17 77.180.224.197=koln-4db4e0c5.pool.einsundeins.de 3,771 0.60
18 79.219.147.49=p4FDB9331.dip0.t-ipconnect.de 3,715 0.59
19 84.163.68.110=p54A3446E.dip.t-dialin.net 3,424 0.55
20 79.218.72.54=p4FDA4836.dip0.t-ipconnect.de 3,356 0.54
21 84.57.170.220=dslb-084-057-170-220.pools.arcor-ip.net 3,257 0.52
22 84.58.221.23=dslb-084-058-221-023.pools.arcor-ip.net 3,050 0.49
23 79.217.199.188=p4FD9C7BC.dip.t-dialin.net 3,028 0.48
24 79.217.253.26=p4FD9FD1A.dip.t-dialin.net 2,880 0.46
25 64.128.171.4=64-128-171-4.static.twtelecom.net 2,793 0.45
Sum 625,799 100.00

To top of page

Top 25 of 485 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.111=llf320022.crawl.yahoo.net 73 4.11
2 72.30.87.112=llf531192.crawl.yahoo.net 63 3.55
3 66.249.71.207=crawl-66-249-71-207.googlebot.com 47 2.65
4 66.249.71.206=crawl-66-249-71-206.googlebot.com 42 2.36
5 66.249.71.205=crawl-66-249-71-205.googlebot.com 42 2.36
6 208.115.111.244=crawl3.dotnetdotcom.org 28 1.58
7 193.252.149.15=natcrawlbloc02.net.s1.fti.net 22 1.24
8 81.52.143.16=natcrawlbloc03.net.m1.fti.net 21 1.18
9 65.55.217.44=(not found) 18 1.01
10 67.195.37.157=llf320058.crawl.yahoo.net 18 1.01
11 81.52.143.15=natcrawlbloc01.net.m1.fti.net 17 0.96
12 212.143.177.197=(not found) 15 0.84
13 78.46.86.53=crawl1.hetzner.itroot.de 14 0.79
14 58.239.73.120=(not found) 14 0.79
15 88.131.106.16=(not found) 13 0.73
65.55.209.153=msnbot-65-55-209-153.search.msn.
16 13 0.73
com
17 81.52.143.26=natcrawlbloc05.net.m1.fti.net 13 0.73
18 193.47.80.44=crawl8.exabot.com 13 0.73
19 74.6.18.216=llf520138.crawl.yahoo.net 11 0.62
20 193.252.149.16=natcrawlbloc04.net.s1.fti.net 10 0.56
65.55.209.152=msnbot-65-55-209-152.search.msn.
21 10 0.56
com
22 195.26.23.221=terminal-4-221.retsat1.com.pl 9 0.51
65.55.209.154=msnbot-65-55-209-154.search.msn.
23 9 0.51
com
24 118.136.59.85=85.59.136.118.fast.net.id 9 0.51
65.55.209.151=msnbot-65-55-209-151.search.msn.
25 9 0.51
com
Sum 1,776 100.00

To top of page

Top 25 of 77 countries of origin , sorted by number of files

N countries of origin times %


1 net 16,230 30.93
2 Germany 12,845 24.48
3 (unresolved) 7,360 14.03
4 com 2,668 5.08
5 Poland 1,504 2.87
6 Austria 1,467 2.80
7 Netherlands 869 1.66
8 Switzerland 707 1.35
9 Norway 651 1.24
10 Hungary 523 1.00
11 Italy 511 0.97
12 India 511 0.97
13 Russian Federation 431 0.82
14 Brazil 420 0.80
15 Sweden 381 0.73
16 Czech Republic 381 0.73
17 China 376 0.72
18 Indonesia 341 0.65
19 Australia 316 0.60
20 Slovak Republic 315 0.60
21 Lithuania 289 0.55
22 org 264 0.50
23 Belgium 241 0.46
24 Finland 214 0.41
25 Greece 185 0.35
Sum 52,473 100.00

To top of page

Top 25 of 120 pathes , sorted by number of files

N pathes times %
1 /common/ 18,406 35.08
2 /avr_gra/ 9,296 17.72
3 / 6,111 11.65
4 /avr_en/beginner/ 1,925 3.67
5 /avr_de/ 1,673 3.19
6 /avr_de/beginner/ 1,672 3.19
7 /avr_en/ 1,589 3.03
8 /avr_en/calc/ 875 1.67
9 /avr_de/rechnen/ 852 1.62
10 /avr_de/praesentation/ 754 1.44
11 /avr_de/fcount/ 646 1.23
12 /avr_de/stepper/ 619 1.18
13 /avr_de/quellen/ 591 1.13
14 /avr_en/source/ 567 1.08
15 /gavrasm/ 487 0.93
16 /avr_en/keypad/ 473 0.90
17 /avr_de/keypad/ 435 0.83
18 /avr_en/signalgen/pics/ 396 0.75
19 /avr_en/stepper/ 387 0.74
20 /avr_de/interrupts/ 356 0.68
21 /avr_de/zeitschleifen/ 328 0.63
/avr_de/rechteckgen/
22 311 0.59
bilder/
23 /gavrasm/v22/ 237 0.45
24 /akkuload/ 202 0.38
25 /privat/magloop/ 189 0.36
Sum 52,473 100.00

To top of page

Top 25 of 120 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 131,187 20.96
2 /avr_gra/ 83,785 13.39
3 /avr_de/intro/pdf/ 51,948 8.30
4 / 36,681 5.86
5 /avr_de/ 27,656 4.42
6 /gavrasm/v22/ 27,476 4.39
7 /avr_de/fcount/ 25,084 4.01
8 /avr_en/ 21,610 3.45
9 /avr_en/beginner/ 16,449 2.63
10 /avr_de/stepper/ 16,400 2.62
11 /avr_de/beginner/ 16,163 2.58
12 /avr_de/intro/ppt/ 11,635 1.86
13 /avr_en/signalgen/pics/ 10,825 1.73
14 /avr_en/stepper/ 9,634 1.54
15 /privat/magloop/ 9,351 1.49
16 /common/ 8,826 1.41
17 /avr_en/calc/ 8,591 1.37
/avr_de/rechteckgen/
18 8,265 1.32
bilder/
19 /avr_en/signalgen/ 7,956 1.27
20 /avr_de/rechnen/ 7,909 1.26
21 /weblox_de/ 7,587 1.21
22 /weblox_en/ 7,416 1.19
23 /akkuload/ 5,153 0.82
24 /privat/Weihnachten2008/ 4,637 0.74
25 /avr_de/interrupts/ 3,866 0.62
Sum 625,799 100.00

To top of page

Top 25 of 1458 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 2,620 4.99
2 /avr_gra/RingLogo.jpg 1,439 2.74
3 /common/app.gif 1,184 2.26
4 /common/akkuload.gif 1,183 2.25
/common/download.
5 1,183 2.25
gif
6 /common/example.gif 1,180 2.25
7 /common/calc.gif 1,180 2.25
/common/gavrasmw.
8 1,179 2.25
gif
/common/knowhow.
9 1,179 2.25
gif
10 /common/gavrasm.gif 1,178 2.24
11 /common/adc.gif 1,177 2.24
12 /common/r2r.gif 1,176 2.24
13 /common/hardware.gif 1,175 2.24
14 /common/beginner.gif 1,174 2.24
15 /avr_gra/stk_lcd.jpg 1,173 2.24
16 /common/clock.gif 1,172 2.23
17 /common/keyb.gif 1,170 2.23
18 /index.html 875 1.67
19 /avr_de/index.html 731 1.39
20 /avr_en/index.html 663 1.26
21 /avr-asm-tutorial.gif 654 1.25
22 /avr_2313.gif 654 1.25
23 /dg4fac.gif 650 1.24
24 /common/tn13.gif 640 1.22
25 /common/delay.gif 638 1.22
Sum 52,473 100.00

To top of page

Top 25 of 1458 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 38,847 6.21
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 38,475 6.15
3 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 18,996 3.04
4 /avr_de/index.html 17,185 2.75
5 /avr_en/index.html 13,697 2.19
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 13,207 2.11
pdf
7 /avr_2313.gif 11,784 1.88
8 /avr_gra/tn13_exp.jpg 11,497 1.84
9 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 11,343 1.81
10 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 11,074 1.77
11 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 10,543 1.68
12 /avr_de/intro/pdf/Teil1_Prozessor.pdf 7,259 1.16
13 /dg4fac.gif 7,016 1.12
14 /gavrasm/v22/gavrasm_win_en_22.zip 5,826 0.93
15 /avr_gra/pwm_simul.jpg 5,469 0.87
16 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 5,443 0.87
17 /avr_gra/tn13_exp.gif 5,208 0.83
18 /favicon.ico 5,129 0.82
19 /gavrasm/v22/gavrasm_win_de_22.zip 4,997 0.80
20 /avr_en/signalgen/pics/rectgen_wiring.jpg 4,937 0.79
21 /avr_de/fcount/dscf0004.jpg 4,884 0.78
22 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 4,876 0.78
23 /avr_gra/exp2313.gif 4,860 0.78
24 /avr_gra/r2r_hardware.jpg 4,725 0.76
25 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 4,666 0.75
Sum 625,799 100.00

To top of page

Top 25 of 427 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 875 7.72
2 /avr_de/index.html 731 6.45
3 /avr_en/index.html 663 5.85
4 /avr_en/beginner/index.html 328 2.89
5 /avr_en/beginner/RIGHT.html 324 2.86
6 /avr_en/beginner/LEFT.html 319 2.81
7 /avr_de/beginner/index.html 263 2.32
8 /avr_de/beginner/links.html 255 2.25
9 /avr_de/beginner/rechts.html 252 2.22
/avr_en/beginner/HARDWARE.
10 144 1.27
html
11 /avr_de/beginner/hardware.html 142 1.25
12 /avr_en/beginner/REGISTER.html 128 1.13
13 /avr_en/keypad/keyboard.html 114 1.01
14 /avr_de/keypad/keyboard.html 105 0.93
15 /avr_de/apps.html 104 0.92
16 /avr_en/AVR_DAC.html 100 0.88
17 /sitemap_de.html 99 0.87
18 /gavrasm/index_en.html 99 0.87
19 /avr_de/praesentation/index.html 98 0.86
20 /avr_en/beginner/JUMP.html 92 0.81
21 /avr_de/avr_tut.html 89 0.79
22 /avr_de/beginner/werkzeuge.html 89 0.79
23 /gavrasm/index_de.html 88 0.78
24 /avr_de/stepper/stepper.html 88 0.78
25 /avr_de/beginner/register.html 86 0.76
Sum 11,333 100.00

To top of page

Top 25 of 427 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 17,185 12.43
2 /avr_en/index.html 13,697 9.90
3 /index.html 4,614 3.34
4 /avr_de/dcf77uhr.html 3,227 2.33
5 /gb_new.html 2,912 2.11
6 /avr_en/beginner/JUMP.html 2,288 1.65
7 /avr_en/keypad/keyboard.html 2,285 1.65
8 /avr_en/beginner/RIGHT.html 2,280 1.65
9 /avr_de/beginner/sprung.html 2,077 1.50
10 /avr_de/keypad/keyboard.html 2,046 1.48
11 /avr_de/beginner/rechts.html 1,792 1.30
12 /avr_de/beginner/rechnen.html 1,782 1.29
13 /sitemap_de.html 1,620 1.17
14 /avr_en/beginner/CALC.html 1,612 1.17
15 /avr_en/beginner/REGISTER.html 1,547 1.12
16 /avr_en/signalgen/rectgen_m8.html 1,495 1.08
17 /avr_de/interrupts/int_quellen.html 1,480 1.07
18 /avr_de/beginner/hardware.html 1,463 1.06
19 /avr_en/beginner/LEFT.html 1,425 1.03
20 /avr_en/AVR_DAC.html 1,312 0.95
21 /avr_de/stepper/stepper.html 1,312 0.95
22 /avr_de/avr_dac.html 1,242 0.90
/avr_en/beginner/HARDWARE.
23 1,233 0.89
html
24 /avr_de/beginner/commands.html 1,232 0.89
25 /avr_de/beginner/pdetail.html 1,218 0.88
Sum 138,298 100.00

To top of page

Top 25 of 452 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 1,439 18.50
2 /avr_gra/stk_lcd.jpg 1,173 15.08
3 /avr_gra/exp2313g.jpg 308 3.96
4 /avr_gra/avr_isp.jpg 265 3.41
5 /avr_gra/exp_2313.jpg 264 3.39
6 /avr_gra/tn13_exp.jpg 264 3.39
7 /avr_gra/8515.jpg 233 3.00
8 /avr_gra/r2r_wave.jpg 156 2.01
9 /avr_gra/AT90S8515.jpg 148 1.90
10 /avr_gra/r2r_sawtooth.jpg 144 1.85
11 /avr_gra/r2r_hardware.jpg 143 1.84
12 /avr_gra/r2r_sawtoothupperbound.jpg 137 1.76
13 /avr_gra/r2r_sawtooth741.jpg 137 1.76
14 /avr_gra/r2r_triangle.jpg 137 1.76
15 /avr_gra/apps.jpg 136 1.75
16 /avr_gra/r2r_upperbound.jpg 135 1.74
17 /avr_gra/pwm_simul.jpg 98 1.26
18 /akkuload/dscf0030s.jpg 96 1.23
19 /avr_gra/adc8conn.jpg 95 1.22
20 /avr_de/stepper/stepper_sm.jpg 90 1.16
21 /avr_de/praesentation/zuendtester.jpg 86 1.11
/avr_en/signalgen/pics/rectgen_280.
22 83 1.07
jpg
23 /avr_de/stepper/driver.jpg 82 1.05
24 /avr_de/stepper/supply.jpg 80 1.03
25 /avr_de/stepper/kp4m4-001.jpg 80 1.03
Sum 7,777 100.00

To top of page

Top 25 of 278 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 1,184 4.30
2 /common/akkuload.gif 1,183 4.30
/common/download.
3 1,183 4.30
gif
4 /common/example.gif 1,180 4.29
5 /common/calc.gif 1,180 4.29
/common/gavrasmw.
6 1,179 4.28
gif
/common/knowhow.
7 1,179 4.28
gif
8 /common/gavrasm.gif 1,178 4.28
9 /common/adc.gif 1,177 4.28
10 /common/r2r.gif 1,176 4.27
11 /common/hardware.gif 1,175 4.27
12 /common/beginner.gif 1,174 4.26
13 /common/clock.gif 1,172 4.26
14 /common/keyb.gif 1,170 4.25
15 /avr-asm-tutorial.gif 654 2.38
16 /avr_2313.gif 654 2.38
17 /dg4fac.gif 650 2.36
18 /common/tn13.gif 640 2.32
19 /common/delay.gif 638 2.32
20 /common/ints.gif 638 2.32
21 /avr_gra/2313.gif 539 1.96
22 /avr_gra/exp2313.gif 274 1.00
23 /avr_gra/avr_isp.gif 263 0.96
24 /avr_gra/isp6pin.gif 261 0.95
25 /avr_gra/tn13_exp.gif 261 0.95
Sum 27,529 100.00

To top of page

Top 25 of 151 entry pages , sorted by number of files

N entry pages times %


1 /index.html 442 19.55
2 /avr_de/index.html 237 10.48
3 /avr_en/index.html 230 10.17
4 /avr_en/beginner/index.html 93 4.11
5 /avr_de/beginner/index.html 60 2.65
6 /avr_en/beginner/HARDWARE.html 45 1.99
7 /avr_de/stepper/stepper.html 44 1.95
8 /avr_en/AVR_DAC.html 38 1.68
9 /avr_de/intro/index.html 38 1.68
10 /avr_en/keypad/keyboard.html 35 1.55
11 /avr_de/beginner/hardware.html 35 1.55
12 /avr_de/keypad/keyboard.html 34 1.50
13 /avr_en/signalgen/rectgen_m8.html 33 1.46
14 /avr_de/avr_dac.html 32 1.42
15 /avr_en/AVR_ADC500.html 28 1.24
/avr_de/rechteckgen/rectgen_m8.
16 28 1.24
html
17 /avr_de/fcount/fcount_m8.html 24 1.06
18 /avr_en/beginner/REGISTER.html 23 1.02
19 /avr_de/rechnen/konversion.html 22 0.97
20 /gb_new.html 22 0.97
21 /avr_en/stepper/stepper.html 21 0.93
22 /avr_de/lcd4_500.html 19 0.84
23 /avr_de/rechnen/multiplikation.html 19 0.84
24 /avr_de/beginner/rechnen.html 19 0.84
25 /akkuload/de/index.html 18 0.80
Sum 2,261 100.00

To top of page

Top 25 of 182 cheat pages , sorted by number of files

N cheat pages times %


1 533 17.42
2 /index.html 244 7.97
3 /avr_de/index.html 219 7.16
4 /avr_en/index.html 201 6.57
5 /avr_en/beginner/RIGHT.html 67 2.19
6 /avr_de/beginner/hardware.html 57 1.86
7 /avr_en/beginner/HARDWARE.html 56 1.83
8 /avr_en/keypad/keyboard.html 54 1.76
9 /avr_en/AVR_DAC.html 50 1.63
10 /avr_de/stepper/stepper.html 49 1.60
11 /avr_de/keypad/keyboard.html 48 1.57
12 /avr_de/intro/index.html 40 1.31
13 /avr_de/beginner/rechts.html 38 1.24
14 /avr_de/avr_dac.html 38 1.24
15 /akkuload/de/index.html 36 1.18
16 /avr_en/beginner/REGISTER.html 35 1.14
17 /avr_de/fcount/fcount_m8.html 31 1.01
18 /avr_en/AVR_ADC500.html 29 0.95
19 /avr_de/praesentation/index.html 26 0.85
/avr_de/rechteckgen/rectgen_m8.
20 25 0.82
html
21 /gavrasm/index_de.html 23 0.75
22 /avr_de/beginner/rechnen.html 23 0.75
23 /avr_de/beginner/diraus.html 23 0.75
24 /avr_de/beginner/werkzeuge.html 22 0.72
25 /avr_de/beginner/sprung.html 22 0.72
Sum 3,060 100.00

To top of page

Top 25 of 144 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 859 15.29
2 /avr_en/beginner/index.html 555 9.88
3 /avr_en/index.html 443 7.89
4 /avr_de/beginner/index.html 429 7.64
5 / 366 6.52
6 /avr_en/beginner/RIGHT.html 255 4.54
7 /avr_de/beginner/rechts.html 239 4.25
8 /avr_en/ 232 4.13
9 /avr_en/beginner/LEFT.html 224 3.99
10 /sitemap_de.html 211 3.76
11 /avr_de/beginner/links.html 165 2.94
12 /sitemap_en.html 107 1.90
13 /index.html 105 1.87
14 /avr_de/interrupts/index.html 90 1.60
15 /avr_de/apps.html 87 1.55
16 /weblox_de/index.html 78 1.39
17 /weblox_en/index.html 76 1.35
18 /avr_de/avr_tut.html 70 1.25
19 /avr_en/calc/index.html 68 1.21
20 /avr_en/AVR_TUT.html 66 1.18
21 /avr_en/APPS.html 62 1.10
22 /avr_de/ 61 1.09
23 /avr_de/zeitschleifen/index.html 61 1.09
/avr_en/signalgen/rectgen_m8.
24 37 0.66
html
25 /avr_de/beginner/commands.html 36 0.64
Sum 5,617 100.00

To top of page

Top 25 of 269 external referrers , sorted by number of files

N external referrers times %


1 - 3,527 86.45
2 http://www.webring.com/hub?ring=avr 22 0.54
3 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 19 0.47
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
4 15 0.37
kurs.htm
5 http://www.dg4fac.de/linksunten.html 13 0.32
6 http://www.mikrocontroller.net/articles/AVR 12 0.29
7 http://www.mikrocontroller.net/articles/Linksammlung 11 0.27
8 http://www.dg4fac.de/rechtsunten.html 11 0.27
9 http://www.rowalt.de/mc/avr/linksd.htm 11 0.27
10 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 10 0.25
11 http://www.raw.to/rubriken/private_elektronik.html 8 0.20
12 http://avr-asm.tripod.com/ 8 0.20
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
13 8 0.20
ESC_by1_bz0_bs0.html
14 http://circuit.lt/?section=sch&page=avr.isp.lpt 7 0.17
15 http://www.serasidis.gr/link.htm 7 0.17
16 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 6 0.15
17 http://www.educypedia.be/electronics/avr.htm 5 0.12
http://www.stud.uni-stuttgart.de/studweb/users/etk/etk39219/avrc/index
18 5 0.12
.htm
19 http://www.avr-asm-download.de/index.html 5 0.12
20 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 5 0.12
21 http://www.outertech.com 5 0.12
22 http://it.wikipedia.org/wiki/Atmel_AVR 5 0.12
http://www.avrfreaks.net/index.php?
23 name=PNphpBB2&file=viewtopic&t=3698 4 0.10
8
24 http://www.bigmike.it/ircontrol/ 4 0.10
http://electrons.psychogenic.com/modules/arms/art/3/
25 AVRGCCProgrammingG 4 0.10
uide.php
Sum 4,080 100.00

To top of page

Top 25 of 98 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 650 42.54
2 http://www.google.com 268 17.54
3 http://www.google.at 60 3.93
4 http://www.google.pl 37 2.42
5 http://www.google.co.in 33 2.16
6 http://www.google.co.uk 25 1.64
7 http://www.google.ch 24 1.57
8 http://www.google.ca 22 1.44
http://www.google.com.
9 20 1.31
au
http://de.search.yahoo.
10 20 1.31
com
11 http://www.google.ro 16 1.05
http://www.google.com.
12 15 0.98
vn
13 http://www.google.be 15 0.98
14 http://www.google.com.tr 14 0.92
15 http://www.google.nl 14 0.92
16 http://www.google.hu 13 0.85
17 http://www.google.co.id 13 0.85
18 http://www.google.sk 12 0.79
19 http://www.google.es 11 0.72
20 http://www.google.pt 11 0.72
21 http://search.live.com 10 0.65
22 http://www.google.se 10 0.65
23 http://www.google.cz 10 0.65
http://www.google.com.
24 9 0.59
br
25 http://www.google.gr 9 0.59
Sum 1,528 100.00

To top of page

Top 25 of 1073 search strings , sorted by number of files

N search strings times %


1 avr tutorial 41 2.68
2 avr 36 2.36
3 avr assembler 33 2.16
4 attiny13 18 1.18
5 avr asm 16 1.05
6 avr assembly 12 0.79
7 ATtiny13 12 0.79
8 avr assembly tutorial 12 0.79
9 avr programming 11 0.72
10 avr grundlagen 10 0.65
11 AVR tutorial 8 0.52
12 stk500 7 0.46
13 Assembler 7 0.46
14 atmel avr 7 0.46
15 assembler 6 0.39
16 avr assembler tutorial 6 0.39
17 assembler avr 6 0.39
18 gavrasm 6 0.39
19 schrittmotorsteuerung 6 0.39
20 avr befehle 6 0.39
21 assembler tutorial 6 0.39
22 AVR assembler 5 0.33
23 avr programing 5 0.33
24 STK500 5 0.33
25 assembler lernen 5 0.33
Sum 1,528 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 46,881 89.34
2 304 Not changed 4,857 9.26
3 206 Partial information 378 0.72
4 301 Permanently moved 161 0.31

http://www.avr-asm-tutorial.net/weblox_en/2009w01.html (1 of 2)1/20/2009 8:03:41 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 404 File not found 136 0.26


6 405 Method not allowed 51 0.10
7 403 Forbidden 5 0.01
8 300 Multiple choices 3 0.01
9 xxx Unknown error 1 0.00
Sum 52,473 100.00

To top of page

Top 25 of 57 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 49 36.03
2 /beginner_de.pdf 13 9.56
3 /avr_de/interrupts/undefined 10 7.35
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
4 20la 3 2.21
nguage_files/LEFT.htm
5 /avr_en/index.html 3 2.21
6 /avr_de/interrupts/int_pic.gif 3 2.21
7 /avr_de/avr_gra/8515.jpg 3 2.21
8 /cgicounter.onlinehome.de/cgi-bin/cnt.gif 2 1.47
9 /keypad/gb_new.html 2 1.47
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
10 20la 1 0.74
nguage_files/HARDWARE.htm
11 /avr_de/intro/ppt/beispiel10_snd.wav 1 0.74
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
12 20la 1 0.74
nguage_files/SRAM.htm
13 /avr_en/beginner/port_files/LEFT.htm 1 0.74
14 /avr_en/beginner/register_files/LEFT.htm 1 0.74
15 /avr_en/beginner/register_files/REGISTER.htm 1 0.74
16 /avr_en/beginner/program_files/LEFT.htm 1 0.74
17 /avr_en/beginner/program_files/JUMP.htm 1 0.74
18 /avr_en/beginner/calculation_files/LEFT.htm 1 0.74
19 /avr_en/beginner/calculation_files/CALC.htm 1 0.74
20 /avr_en/beginner/table_files/COMMANDS.htm 1 0.74
21 /avr_en/beginner/table_files/LEFT.htm 1 0.74
22 /cgicounter.onlinehome.de/cgi-bin/cnt_2.gif 1 0.74
23 /avr_de/keypad/gb_new.html 1 0.74
/_vti_bin/owssvr.dll?
24 1 0.74
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
25 1 0.74
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
Sum 136 100.00

To top of page

Top 25 of 80 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 28,640 54.58
2 Mozilla/4.0 18,562 35.37
3 Opera/9.63 1,029 1.96
4 Opera/9.62 937 1.79
5 Yanga 511 0.97
echobot/echobot-
6 348 0.66
v0.5
7 Opera/9.52 263 0.50
8 msnbot-media/1.1 242 0.46
9 msnbot/1.1 194 0.37
10 Opera/9.61 187 0.36
11 WebCopier v4.6 182 0.35
12 - 150 0.29
13 Ocelli/1.4 138 0.26
14 Opera/9.20 122 0.23
15 Safari5525.27.1 115 0.22
Googlebot-
16 108 0.21
Image/1.0
17 Opera/9.24 91 0.17
18 Opera/9.60 86 0.16
19 Opera/9.25 77 0.15
20 Opera/9.27 70 0.13
21 Opera/10.00 49 0.09
22 Java/1.6.0_04 48 0.09
23 Opera/9.50 38 0.07
24 Speedy 37 0.07
25 Opera/9.51 21 0.04
Sum 52,473 100.00

To top of page

Top 25 of 197 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 15,873 30.25
2 MSIE 7.0 9,924 18.91
3 MSIE 6.0 6,367 12.13
4 Gecko 1,651 3.15
5 Firefox/2.0.0.20 1,593 3.04
6 Firefox/3.0.5 1,589 3.03
7 FDM 1,390 2.65
8 Opera/9.63 1,027 1.96
9 Opera/9.62 937 1.79
10 Firefox/3.0.4 895 1.71
11 unknown 783 1.49
12 Firefox/3.0.1 689 1.31
13 Firefox/3.0.3 676 1.29
14 Slurp 669 1.27
15 Firefox/3.0 356 0.68
16 crawler 350 0.67
17 Avant Browser 273 0.52
18 Opera/9.52 263 0.50
19 msnbot-media/1.1 242 0.46
20 Googlebot/2.1 237 0.45
crawler@dotnetdotcom.
21 223 0.42
org
22 Firefox/2.0.0.12 218 0.42
23 Firefox/2.0.0.18 217 0.41
24 msnbot/1.1 194 0.37
25 Firefox/2.0.0.14 190 0.36
Sum 52,473 100.00

To top of page

Top 25 of 29 operating systems , sorted by number of files

N operating systems times %


1 Windows 22,582 43.04
2 Windows NT 5.1 16,481 31.41
3 unknown 3,826 7.29
4 Windows NT 6.0 3,094 5.90
5 Linux i686 2,922 5.57
6 Windows NT 5.0 1,413 2.69
7 Mac OS X 10_5_6 386 0.74
8 Linux x86_64 366 0.70
9 Mac OS X 10.5 306 0.58
10 Windows 98 243 0.46
11 Mac OS X 10_4_11 173 0.33
12 Linux 146 0.28
13 Linux i686 100 0.19
14 Mac OS X 98 0.19
15 Windows XP 5.1 88 0.17
16 Mac OS X 10_5_5 57 0.11
17 Windows NT 5.2 54 0.10
18 Windows 6.0 51 0.10
19 Mac OS X 10.4 36 0.07
20 Linux i586 21 0.04
21 SunOS i86pc 13 0.02
22 X11 6 0.01
23 Win16 2 0.00
Linux 2.6.27-9-
24 2 0.00
generic
25 Windows server 2 0.00
Sum 52,473 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 1,857 3.54
2 01 1,489 2.84
3 02 967 1.84
4 03 716 1.36
5 04 790 1.51
6 05 781 1.49
7 06 938 1.79
8 07 819 1.56
9 08 1,123 2.14
10 09 1,667 3.18
11 10 2,025 3.86
12 11 1,812 3.45
13 12 2,327 4.43
14 13 2,320 4.42
15 14 2,876 5.48
16 15 3,111 5.93
17 16 4,202 8.01
18 17 3,306 6.30
19 18 3,121 5.95
20 19 3,680 7.01
21 20 3,511 6.69
22 21 3,334 6.35
23 22 3,004 5.72
24 23 2,697 5.14
Sum 52,473 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2009w01.html (2 of 2)1/20/2009 8:03:41 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2008y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 220480 IPs and host names , sorted by number of files

N IPs and host names times %


1 220.245.179.132=nme-nxg-pr3.tpgi.com.au 9,750 0.21
2 77.91.224.10=(not found) 8,269 0.18
3 91.205.124.9=(not found) 7,574 0.16
4 67.195.37.109=llf320031.crawl.yahoo.net 7,559 0.16
5 66.249.72.79=crawl-66-249-72-79.googlebot.com 6,106 0.13
6 217.7.228.75=pd907e44b.dip0.t-ipconnect.de 4,777 0.10
7 77.88.25.28=spider33.yandex.ru 4,525 0.10
8 67.195.37.183=llf320052.crawl.yahoo.net 4,481 0.10
9 77.91.224.20=(not found) 4,414 0.10
10 85.17.173.6=hosted-by.leaseweb.com 4,117 0.09
11 77.91.224.9=(not found) 4,078 0.09
12 194.39.218.10=http-v.fe.bosch.de 4,003 0.09
13 217.194.34.103=inac.erlm.siemens.de 4,002 0.09
14 208.111.154.16=crawl2.nat.svl.searchme.com 3,884 0.08
15 208.111.154.15=crawl1.nat.svl.searchme.com 3,802 0.08
16 68.42.139.41=c-68-42-139-41.hsd1.mi.comcast.net 3,705 0.08
17 85.17.173.2=hosted-by.leaseweb.com 3,663 0.08
18 213.25.33.100=(not found) 3,329 0.07
19 77.79.25.43=hst-25-43.splius.lt 3,325 0.07
20 85.17.173.8=hosted-by.leaseweb.com 3,200 0.07
21 83.103.132.12=Home03362.cluj.astral.ro 3,059 0.07
78.137.163.133=ip-78-137-163-133.dedi.digiweb.
22 3,046 0.07
ie
23 146.230.128.29=dbnproxy1.ukzn.ac.za 3,010 0.07
24 65.55.212.136=(not found) 2,982 0.06
66.249.65.145=crawl-66-249-65-145.googlebot.
25 2,930 0.06
com
Sum 4,619,528 100.00

To top of page

Top 25 of 220480 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 220.245.179.132=nme-nxg-pr3.tpgi.com.au 213,559 0.45
2 91.205.124.9=(not found) 140,316 0.30
3 67.195.37.109=llf320031.crawl.yahoo.net 111,422 0.23
4 77.91.224.10=(not found) 87,350 0.18
5 77.88.25.28=spider33.yandex.ru 83,057 0.17
6 68.142.212.236=crm77.image.search.mud.yahoo.net 82,439 0.17
7 83.103.132.12=Home03362.cluj.astral.ro 81,139 0.17
8 65.55.212.136=(not found) 78,847 0.17
9 66.249.72.79=crawl-66-249-72-79.googlebot.com 78,022 0.16
10 65.55.212.137=(not found) 69,364 0.15
11 77.46.254.36=(not found) 65,823 0.14
12 67.195.37.183=llf320052.crawl.yahoo.net 63,626 0.13
13 217.194.34.103=inac.erlm.siemens.de 63,075 0.13
14 125.161.205.69=69.subnet125-161-205.speedy.telkom.net.id 60,349 0.13
15 88.131.106.16=(not found) 60,175 0.13
16 194.39.218.10=http-v.fe.bosch.de 55,264 0.12
17 66.231.189.88=(not found) 53,102 0.11
18 85.17.173.6=hosted-by.leaseweb.com 48,141 0.10
19 77.91.224.20=(not found) 47,270 0.10
20 193.149.14.116=lingia.exp.bessy.de 46,185 0.10
125.160.136.194=194.subnet125-160-136.speedy.telkom.net.
21 45,897 0.10
id
22 213.195.215.130=srv.spcnet.cz 45,280 0.10
23 85.17.173.2=hosted-by.leaseweb.com 42,772 0.09
24 194.121.90.163=out-gate01.becker.de 42,385 0.09
25 74.6.17.163=llf520189.crawl.yahoo.net 41,132 0.09
Sum 47,488,565 100.00

To top of page

Top 25 of 41522 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


1 72.14.195.49=(not found) 1,864 0.75
2 67.195.37.109=llf320031.crawl.yahoo.net 1,311 0.53
3 193.252.149.15=natcrawlbloc02.net.s1.fti.net 1,217 0.49
4 88.131.106.16=(not found) 1,208 0.49
5 81.52.143.16=natcrawlbloc03.net.m1.fti.net 1,156 0.47
6 208.111.154.15=crawl1.nat.svl.searchme.com 1,141 0.46
7 81.52.143.15=natcrawlbloc01.net.m1.fti.net 1,103 0.44
8 67.195.37.183=llf320052.crawl.yahoo.net 1,035 0.42
9 208.111.154.16=crawl2.nat.svl.searchme.com 1,023 0.41
10 193.47.80.44=crawl8.exabot.com 944 0.38
11 66.249.72.79=crawl-66-249-72-79.googlebot.com 902 0.36
12 65.214.45.119=crawler4010.ask.com 869 0.35
13 66.249.84.15=(not found) 741 0.30
14 67.195.37.169=llf320041.crawl.yahoo.net 688 0.28
15 66.231.189.88=(not found) 679 0.27
16 38.99.13.125=crawl-4.cuill.com 675 0.27
17 193.252.149.16=natcrawlbloc04.net.s1.fti.net 615 0.25
18 66.249.71.207=crawl-66-249-71-207.googlebot.com 582 0.23
19 66.249.71.205=crawl-66-249-71-205.googlebot.com 558 0.22
20 66.249.71.206=crawl-66-249-71-206.googlebot.com 540 0.22
21 74.6.31.163=dj531029.crawl.yahoo.net 454 0.18
22 220.181.61.229=(not found) 453 0.18
65.55.209.153=msnbot-65-55-209-153.search.msn.
23 433 0.17
com
24 65.55.212.136=(not found) 429 0.17
25 67.195.37.185=llf320047.crawl.yahoo.net 427 0.17
Sum 248,280 100.00

To top of page

Top 25 of 304 countries of origin , sorted by number of files

N countries of origin times %


1 net 1,248,981 27.04
2 Germany 978,094 21.17
3 (unresolved) 840,898 18.20
4 com 319,849 6.92
5 Austria 110,540 2.39
6 Poland 107,248 2.32
7 Switzerland 66,658 1.44
8 Netherlands 60,961 1.32
9 Australia 52,503 1.14
10 Italy 48,260 1.04
11 Indonesia 44,821 0.97
12 Hungary 37,549 0.81
13 India 37,075 0.80
14 Czech Republic 34,358 0.74
15 Brazil 33,716 0.73
16 Romania 32,166 0.70
17 Mexico 31,854 0.69
18 Lithuania 30,415 0.66
19 Greece 29,345 0.64
20 Canada 28,760 0.62
21 edu 28,758 0.62
22 Russian Federation 26,801 0.58
23 Sweden 26,203 0.57
24 Belgium 24,158 0.52
25 Finland 22,980 0.50
Sum 4,619,528 100.00

To top of page

Top 25 of 2262 pathes , sorted by number of files

N pathes times %
1 /common/ 1,580,606 34.22
2 /avr_gra/ 803,772 17.40
3 / 558,412 12.09
4 /avr_en/beginner/ 198,302 4.29
5 /avr_de/beginner/ 158,373 3.43
6 /avr_en/ 148,948 3.22
7 /avr_de/ 138,246 2.99
8 /avr_en/calc/ 84,802 1.84
9 /avr_de/fcount/ 75,188 1.63
10 /avr_de/rechnen/ 65,390 1.42
11 /avr_en/keypad/ 59,007 1.28
12 /avr_en/source/ 58,422 1.26
13 /avr_de/stepper/ 54,003 1.17
14 /avr_de/praesentation/ 53,710 1.16
15 /avr_de/quellen/ 50,073 1.08
16 /avr_en/signalgen/pics/ 37,895 0.82
17 /avr_en/stepper/ 35,559 0.77
18 /avr_de/rechteckgen/bilder/ 35,352 0.77
19 /gavrasm/ 33,848 0.73
20 /avr_de/keypad/ 33,441 0.72
21 /akkuload/ 18,693 0.40
22 /avr_de/zeitschleifen/ 16,363 0.35
/privat/stechlin/rundgang/
23 16,263 0.35
thumbs/
24 /avr_en/signalgen/ 16,170 0.35
25 /privat/stechlin/ 15,258 0.33
Sum 4,619,528 100.00

To top of page

Top 25 of 2262 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 8,766,001 18.46
2 /avr_gra/ 6,351,450 13.37
3 /avr_de/intro/pdf/ 3,572,799 7.52
4 / 2,990,688 6.30
5 /avr_de/fcount/ 2,871,873 6.05
6 /avr_de/ 2,121,754 4.47
7 /avr_en/ 2,051,692 4.32
8 /avr_en/beginner/ 1,650,628 3.48
9 /avr_de/beginner/ 1,490,260 3.14
10 /avr_de/stepper/ 1,421,149 2.99
11 /gavrasm/v21/ 998,246 2.10
12 /avr_en/signalgen/pics/ 998,185 2.10
/avr_de/rechteckgen/
13 956,902 2.02
bilder/
14 /avr_en/stepper/ 870,171 1.83
15 /avr_en/calc/ 781,046 1.64
16 /common/ 708,890 1.49
17 /avr_de/rechnen/ 597,236 1.26
18 /avr_en/signalgen/ 593,091 1.25
19 /avr_en/keypad/ 574,252 1.21
20 /avr_de/rechteckgen/ 524,174 1.10
21 /avr_de/intro/ppt/ 510,404 1.07
22 /akkuload/ 463,012 0.97
23 /privat/magloop/ 414,055 0.87
24 /weblox_de/ 359,247 0.76
25 /weblox_en/ 317,818 0.67
Sum 47,488,565 100.00

To top of page

Top 25 of 6357 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 250,970 5.43
2 /avr_gra/RingLogo.jpg 128,085 2.77
/common/knowhow.
3 106,226 2.30
gif
4 /common/app.gif 106,066 2.30
5 /common/akkuload.gif 105,994 2.29
6 /common/clock.gif 105,831 2.29
7 /common/gavrasm.gif 105,818 2.29
8 /avr_gra/stk_lcd.jpg 105,594 2.29
9 /common/example.gif 105,574 2.29
10 /common/beginner.gif 105,474 2.28
/common/gavrasmw.
11 105,447 2.28
gif
12 /common/r2r.gif 105,426 2.28
13 /common/calc.gif 105,416 2.28
14 /common/adc.gif 105,337 2.28
15 /common/hardware.gif 105,310 2.28
16 /common/keyb.gif 105,299 2.28
/common/download.
17 99,733 2.16
gif
18 /index.html 72,664 1.57
19 /avr_en/index.html 65,603 1.42
20 /avr_de/index.html 57,957 1.25
21 /avr_2313.gif 56,866 1.23
22 /dg4fac.gif 55,706 1.21
23 /avr-asm-tutorial.gif 55,508 1.20
24 /avr_gra/2313.gif 52,770 1.14
25 /common/tn13.gif 50,611 1.10
Sum 4,619,528 100.00

To top of page

Top 25 of 6357 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 2,778,570 5.85
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 1,675,687 3.53
3 /avr_en/index.html 1,322,878 2.79
4 /avr_de/index.html 1,284,574 2.71
5 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 1,034,225 2.18
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 1,032,081 2.17
pdf
7 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 983,174 2.07
8 /avr_2313.gif 981,582 2.07
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 967,150 2.04
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 878,389 1.85
11 /avr_gra/pwm_simul.jpg 598,421 1.26
12 /dg4fac.gif 587,691 1.24
13 /avr_de/fcount/dscf0004.jpg 567,381 1.19
14 /avr_gra/r2r_hardware.jpg 498,349 1.05
15 /avr_de/fcount/dscf0005.jpg 490,987 1.03
16 /avr_de/fcount/dscf0001.jpg 463,903 0.98
17 /favicon.ico 458,478 0.97
18 /avr_en/signalgen/pics/rectgen_wiring.jpg 457,231 0.96
19 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 450,509 0.95
20 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 442,871 0.93
21 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 441,845 0.93
22 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 429,075 0.90
23 /avr_gra/exp2313.gif 392,610 0.83
24 /index.html 382,619 0.81
25 /avr_gra/2313.gif 370,948 0.78
Sum 47,488,565 100.00

To top of page

Top 25 of 2846 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 72,664 7.05
2 /avr_en/index.html 65,603 6.37
3 /avr_de/index.html 57,957 5.63
4 /avr_en/beginner/index.html 34,677 3.37
5 /avr_en/beginner/LEFT.html 33,838 3.29
6 /avr_en/beginner/RIGHT.html 33,213 3.22
7 /avr_de/beginner/index.html 24,737 2.40
8 /avr_de/beginner/links.html 24,164 2.35
9 /avr_de/beginner/rechts.html 23,376 2.27
/avr_en/beginner/HARDWARE.
10 14,658 1.42
html
11 /avr_en/beginner/REGISTER.html 11,433 1.11
12 /avr_en/keypad/keyboard.html 10,384 1.01
13 /avr_de/beginner/hardware.html 9,666 0.94
14 /avr_en/beginner/JUMP.html 9,323 0.91
15 /avr_en/AVR_DAC.html 9,245 0.90
16 /avr_de/beginner/register.html 8,318 0.81
17 /avr_de/praesentation/index.html 8,262 0.80
18 /avr_en/beginner/TOOLS.html 8,121 0.79
19 /avr_de/beginner/sprung.html 8,121 0.79
20 /avr_en/beginner/PORTS.html 7,862 0.76
21 /avr_en/AVR_ADC500.html 7,747 0.75
22 /avr_de/apps.html 7,742 0.75
23 /avr_en/AVR_TUT.html 7,606 0.74
24 /avr_de/stepper/stepper.html 7,594 0.74
25 /avr_de/beginner/werkzeuge.html 7,572 0.74
Sum 1,030,069 100.00

To top of page

Top 25 of 2846 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 1,322,878 11.34
2 /avr_de/index.html 1,284,574 11.01
3 /index.html 382,619 3.28
4 /gb_new.html 239,269 2.05
5 /avr_en/beginner/RIGHT.html 237,248 2.03
6 /avr_de/beginner/sprung.html 222,250 1.90
7 /avr_en/beginner/JUMP.html 218,570 1.87
8 /avr_de/dcf77uhr.html 214,314 1.84
9 /avr_en/keypad/keyboard.html 207,926 1.78
10 /avr_de/beginner/rechnen.html 165,879 1.42
11 /avr_de/beginner/rechts.html 161,886 1.39
12 /avr_en/beginner/CALC.html 154,193 1.32
13 /avr_en/beginner/LEFT.html 150,387 1.29
14 /avr_de/keypad/keyboard.html 145,337 1.25
15 /avr_en/beginner/REGISTER.html 134,789 1.16
16 /avr_en/AVR_DAC.html 134,088 1.15
/avr_de/rechteckgen/rectgen_m8.
17 128,606 1.10
html
18 /avr_de/beginner/pdetail.html 128,310 1.10
19 /avr_en/signalgen/rectgen_m8.html 128,227 1.10
20 /avr_en/beginner/PDETAIL.html 124,071 1.06
21 /avr_en/AVR_ADC500.html 120,566 1.03
22 /avr_de/beginner/commands.html 120,053 1.03
23 /avr_de/avr_dac.html 117,660 1.01
/avr_en/beginner/COMMANDS.
24 116,864 1.00
html
25 /avr_de/stepper/stepper.html 112,529 0.96
Sum 11,667,458 100.00

To top of page

Top 25 of 1019 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 128,055 18.50
2 /avr_gra/stk_lcd.jpg 105,592 15.26
3 /avr_gra/8515.jpg 25,103 3.63
4 /avr_gra/exp2313g.jpg 22,115 3.20
5 /avr_gra/avr_isp.jpg 21,619 3.12
6 /avr_gra/exp_2313.jpg 21,311 3.08
7 /avr_gra/r2r_wave.jpg 15,741 2.27
8 /avr_gra/r2r_sawtooth.jpg 14,941 2.16
9 /avr_gra/r2r_hardware.jpg 14,089 2.04
10 /avr_gra/r2r_sawtoothupperbound.jpg 13,994 2.02
11 /avr_gra/r2r_triangle.jpg 13,972 2.02
12 /avr_gra/r2r_sawtooth741.jpg 13,845 2.00
13 /avr_gra/r2r_upperbound.jpg 13,824 2.00
14 /avr_gra/AT90S8515.jpg 12,805 1.85
15 /avr_gra/pwm_simul.jpg 10,850 1.57
16 /avr_gra/adc8conn.jpg 10,822 1.56
17 /avr_gra/apps.jpg 10,423 1.51
18 /akkuload/dscf0030s.jpg 8,861 1.28
19 /avr_en/signalgen/pics/rectgen_280.jpg 8,161 1.18
20 /avr_de/stepper/stepper_sm.jpg 7,637 1.10
/avr_de/rechteckgen/bilder/rectgen_280.
21 7,367 1.06
jpg
22 /avr_de/praesentation/zuendtester.jpg 7,281 1.05
23 /avr_de/stepper/kp4m4-001.jpg 7,062 1.02
24 /avr_de/stepper/supply.jpg 6,985 1.01
25 /avr_de/stepper/driver.jpg 6,903 1.00
Sum 692,089 100.00

To top of page

Top 25 of 635 GIF-files , sorted by number of files

N GIF-files times %
/common/knowhow.
1 106,221 4.49
gif
2 /common/app.gif 106,059 4.48
3 /common/akkuload.gif 105,985 4.48
4 /common/clock.gif 105,825 4.47
5 /common/gavrasm.gif 105,809 4.47
6 /common/example.gif 105,567 4.46
7 /common/beginner.gif 105,471 4.46
/common/gavrasmw.
8 105,441 4.45
gif
9 /common/r2r.gif 105,419 4.45
10 /common/calc.gif 105,403 4.45
11 /common/adc.gif 105,332 4.45
12 /common/hardware.gif 105,307 4.45
13 /common/keyb.gif 105,293 4.45
/common/download.
14 99,709 4.21
gif
15 /avr_2313.gif 56,860 2.40
16 /dg4fac.gif 55,697 2.35
17 /avr-asm-tutorial.gif 55,508 2.34
18 /avr_gra/2313.gif 52,736 2.23
19 /common/tn13.gif 50,607 2.14
20 /common/ints.gif 28,515 1.20
21 /common/delay.gif 28,507 1.20
22 /avr_gra/exp2313.gif 22,398 0.95
23 /avr_gra/avr_isp.gif 21,651 0.91
24 /avr_gra/isp10pin.gif 21,414 0.90
25 /avr_gra/isp6pin.gif 21,380 0.90
Sum 2,367,386 100.00

To top of page

Top 25 of 464 entry pages , sorted by number of files

N entry pages times %


1 /index.html 28,247 16.11
2 /avr_en/index.html 17,937 10.23
3 /avr_de/index.html 14,646 8.35
4 /avr_en/beginner/index.html 7,660 4.37
5 /avr_de/beginner/index.html 5,560 3.17
6 /avr_en/AVR_DAC.html 4,240 2.42
7 /avr_en/beginner/HARDWARE.html 3,638 2.07
8 /avr_de/stepper/stepper.html 3,212 1.83
9 /avr_de/fcount/fcount_m8.html 3,187 1.82
10 /privat/stechlin/index.html 3,137 1.79
11 /avr_de/avr_dac.html 3,133 1.79
/avr_de/rechteckgen/rectgen_m8.
12 2,557 1.46
html
13 /avr_en/keypad/keyboard.html 2,511 1.43
14 /avr_de/keypad/keyboard.html 2,419 1.38
15 /avr_en/signalgen/rectgen_m8.html 2,335 1.33
16 /avr_en/AVR_ADC500.html 2,274 1.30
17 /avr_de/intro/index.html 2,168 1.24
18 /gb_new.html 2,009 1.15
19 /avr_de/rechnen/konversion.html 1,891 1.08
20 /avr_de/beginner/hardware.html 1,801 1.03
21 /akkuload/de/index.html 1,536 0.88
22 /avr_de/beginner/diraus.html 1,522 0.87
23 /avr_en/stepper/stepper.html 1,508 0.86
24 /avr_de/avr_adc500.html 1,412 0.81
25 /avr_de/beginner/rechnen.html 1,351 0.77
Sum 175,365 100.00

To top of page

Top 25 of 700 cheat pages , sorted by number of files

N cheat pages times %


1 22,171 10.06
2 /index.html 16,908 7.67
3 /avr_en/index.html 15,571 7.06
4 /avr_de/index.html 13,194 5.98
5 /avr_en/beginner/RIGHT.html 5,000 2.27
6 /avr_en/AVR_DAC.html 4,693 2.13
7 /avr_en/beginner/HARDWARE.html 4,599 2.09
8 /avr_en/keypad/keyboard.html 3,932 1.78
9 /avr_de/beginner/rechts.html 3,584 1.63
10 /avr_de/stepper/stepper.html 3,485 1.58
11 /avr_de/avr_dac.html 3,387 1.54
12 /avr_de/keypad/keyboard.html 3,187 1.45
13 /avr_de/fcount/fcount_m8.html 3,175 1.44
14 /privat/stechlin/index.html 3,132 1.42
15 /avr_en/AVR_ADC500.html 2,738 1.24
16 /avr_de/beginner/hardware.html 2,733 1.24
17 /avr_en/beginner/REGISTER.html 2,484 1.13
/avr_de/rechteckgen/rectgen_m8.
18 2,375 1.08
html
19 /akkuload/de/index.html 2,341 1.06
20 /avr_en/signalgen/rectgen_m8.html 2,210 1.00
21 /avr_de/beginner/sprung.html 2,115 0.96
22 /avr_de/beginner/rechnen.html 2,107 0.96
23 /avr_de/praesentation/index.html 2,041 0.93
24 /avr_en/beginner/JUMP.html 2,034 0.92
25 /avr_de/intro/index.html 1,997 0.91
Sum 220,480 100.00

To top of page

Top 25 of 375 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 72,797 14.31
2 /avr_en/beginner/index.html 59,359 11.67
3 /avr_en/index.html 52,160 10.25
4 /avr_de/beginner/index.html 40,928 8.04
5 / 32,559 6.40
6 /avr_en/beginner/RIGHT.html 27,763 5.46
7 /avr_de/beginner/rechts.html 20,545 4.04
8 /avr_en/beginner/LEFT.html 19,963 3.92
9 /avr_de/beginner/links.html 17,004 3.34
10 /sitemap_de.html 12,671 2.49
11 /avr_en/ 11,833 2.33
12 /sitemap_en.html 10,324 2.03
13 /avr_en/keypad 9,690 1.90
14 /avr_de/apps.html 7,635 1.50
15 /index.html 7,575 1.49
16 /avr_en/AVR_TUT.html 5,664 1.11
17 /avr_en/calc/index.html 5,473 1.08
18 /avr_de/avr_tut.html 5,107 1.00
19 /avr_de/ 4,614 0.91
20 /weblox_de/index.html 3,928 0.77
21 /avr_en/APPS.html 3,706 0.73
22 /avr_de/rechnen/index.html 3,568 0.70
23 /avr_de/interrupts/index.html 3,564 0.70
24 /avr_de/zeitschleifen/index.html 3,380 0.66
/avr_de/beginner/commands.
25 3,074 0.60
html
Sum 508,845 100.00

To top of page

Top 25 of 6607 external referrers , sorted by number of files

N external referrers times %


1 - 290,438 84.99
2 http://www.mikrocontroller.net/articles/AVR 1,965 0.57
3 http://r.webring.com/hub?ring=avr 1,302 0.38
4 http://de.wikipedia.org/wiki/R2R-Netzwerk 933 0.27
5 http://avr-asm.tripod.com/ 914 0.27
6 http://www.dg4fac.de/linksunten.html 869 0.25
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 851 0.25
8 http://www.educypedia.be/electronics/avr.htm 830 0.24
9 http://www.webring.com/hub?ring=avr 696 0.20
10 http://www.mikrocontroller.net/articles/Linksammlung 661 0.19
11 http://www.dg4fac.de/rechtsunten.html 653 0.19
http://www.avrfreaks.net/index.php?
12 name=PNphpBB2&file=viewtopic&t=3698 649 0.19
8
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
13 646 0.19
ESC_by1_bz0_bs0.html
14 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 602 0.18
15 http://www.rowalt.de/mc/avr/linksd.htm 594 0.17
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
16 551 0.16
kurs.htm
http://electrons.psychogenic.com/modules/arms/art/3/
17 AVRGCCProgrammingG 532 0.16
uide.php
18 http://www.dg4fac.de/stechlin/index.html 492 0.14
19 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 474 0.14
20 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 474 0.14
21 http://todopic.mforos.com/551641/4566219-grabador-para-atmel/ 389 0.11
22 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 382 0.11
23 http://frank.bol.ucla.edu/avr.htm 373 0.11
24 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 370 0.11
25 http://search.webdunia.com/ 363 0.11
Sum 341,750 100.00

To top of page

Top 25 of 610 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 70,755 42.50
2 http://www.google.com 31,338 18.82
3 http://www.google.at 5,075 3.05
4 http://www.google.co.in 4,689 2.82
5 http://www.google.co.uk 3,134 1.88
6 http://www.google.ch 3,028 1.82
7 http://www.google.pl 2,653 1.59
8 http://www.google.ca 2,601 1.56
9 http://www.google.com.au 2,301 1.38
10 http://www.google.nl 2,214 1.33
11 http://www.google.se 1,584 0.95
12 http://www.google.co.id 1,530 0.92
13 http://www.google.it 1,409 0.85
14 http://www.google.ro 1,372 0.82
15 http://www.google.fi 1,365 0.82
16 http://search.yahoo.com 1,308 0.79
17 http://www.google.fr 1,049 0.63
18 http://www.google.hu 1,013 0.61
http://www.google.com.
19 1,002 0.60
mx
http://de.search.yahoo.
20 997 0.60
com
21 http://www.google.gr 974 0.59
22 http://www.google.com.br 963 0.58
23 http://www.google.cz 860 0.52
24 http://www.google.be 820 0.49
25 http://www.google.com.vn 751 0.45
Sum 166,472 100.00

To top of page

Top 25 of 75538 search strings , sorted by number of files

N search strings times %


1 avr tutorial 4,213 2.53
2 avr assembler 2,443 1.47
3 avr 2,036 1.22
4 assembler 1,722 1.03
5 attiny13 1,688 1.01
6 avr programming 1,522 0.91
7 assembler tutorial 1,170 0.70
8 avr asm 866 0.52
9 avr assembly 850 0.51
10 atmega8 752 0.45
avr assembler
11 649 0.39
tutorial
12 ATtiny13 590 0.35
13 AVR tutorial 551 0.33
14 AVR 542 0.33
15 stk500 458 0.28
16 avr asm tutorial 452 0.27
17 gavrasm 396 0.24
assembler
18 395 0.24
commands
19 avr tutorials 369 0.22
20 wavrasm 363 0.22
21 AVR programming 362 0.22
22 Assembler 356 0.21
23 avr assembly tutorial 338 0.20
24 assembler avr 336 0.20
25 atmel assembler 330 0.20
Sum 166,472 100.00

To top of page

Top 13 of 13 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 4,093,799 88.62
2 304 Not changed 454,203 9.83
3 206 Partial information 38,082 0.82
4 404 File not found 20,818 0.45
5 301 Permanently moved 8,927 0.19
6 403 Forbidden 2,121 0.05

http://www.avr-asm-tutorial.net/weblox_en/2008y.html (1 of 2)1/20/2009 8:04:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

7 300 Multiple choices 928 0.02


8 xxx Unknown error 240 0.01
9 xxx Unknown error 209 0.00
10 405 Method not allowed 178 0.00
11 400 Error in request 17 0.00
12 401 Not authorized 5 0.00
13 xxx Unknown error 1 0.00
Sum 4,619,528 100.00

To top of page

Top 25 of 2760 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 2,269 10.90
2 /beginner_de.pdf 1,033 4.96
3 /avr_en/quellen/schrittmotor_v1.asm 497 2.39
4 /avr_en/stepper/schrittmotor_v1.html 442 2.12
5 /_vti_inf.html 432 2.08
/MSOffice/cltreq.asp?
6 198 0.95
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
7 186 0.89
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
8 /_vpi.xml 161 0.77
9 /avr_de/intro/ppt/beispiel10_snd.wav 128 0.61
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
10 %20la 119 0.57
nguage_files/LEFT.htm
/MSOffice/cltreq.asp?
11 116 0.56
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
12 112 0.54
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 111 0.53
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
14 99 0.48
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
15 96 0.46
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
16 /avr_de/praesentation/favicon.ico 57 0.27
17 /avr_de/praesentation/favicon.gif 57 0.27
18 /gavrasm/v16/LiesMich.Txt 52 0.25
19 /gavrasm/v16/DosRead.Txt 48 0.23
20 /gavrasm/v16/instr.asm 47 0.23
21 /sitemap.xml 47 0.23
22 /avr_en/source/TEST2.asm/index.html 47 0.23
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
23 20AVR-Assemble 46 0.22
r-Dateien/links.htm
24 /avr_en/source/TEST1.asm/index.html 45 0.22
25 /avr_en/source/_vpi.xml 45 0.22
Sum 20,818 100.00

To top of page

Top 25 of 1165 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 2,305,400 49.91
2 Mozilla/4.0 1,834,914 39.72
3 Mozilla/4.5 40,713 0.88
4 Opera/9.25 36,626 0.79
5 WebAlta 30,637 0.66
6 Opera/9.27 30,050 0.65
7 Opera/9.26 23,147 0.50
8 Opera/9.50 22,918 0.50
9 Opera/9.51 20,265 0.44
10 Opera/9.52 17,035 0.37
11 Opera/9.24 16,420 0.36
12 Opera/9.62 15,851 0.34
13 msnbot/1.1 15,147 0.33
14 - 11,403 0.25
15 Opera/9.23 10,264 0.22
16 9,955 0.22
17 Opera/9.60 9,641 0.21
18 Yanga 9,231 0.20
19 Yandex/1.01.001 7,917 0.17
20 Opera/9.10 7,210 0.16
Googlebot-
21 7,073 0.15
Image/1.0
22 Opera/9.21 6,472 0.14
23 msnbot-media/1.0 6,142 0.13
24 Opera/9.61 5,432 0.12
25 Opera/9.20 4,741 0.10
Sum 4,619,528 100.00

To top of page

Top 25 of 1994 browser versions , sorted by number of files

N browser versions times %


1 MSIE 7.0 868,738 18.81
2 MSIE 6.0 824,541 17.85
3 Firefox/2.0.0.14 294,245 6.37
4 Firefox/2.0.0.12 247,385 5.36
5 Firefox/2.0.0.11 226,491 4.90
6 Firefox/3.0.1 201,653 4.37
7 Firefox/3.0.3 177,702 3.85
8 Firefox/3.0.4 132,975 2.88
9 Firefox/2.0.0.13 110,052 2.38
10 Firefox/2.0.0.16 102,707 2.22
11 Firefox/3.0 87,247 1.89
12 Gecko 79,952 1.73
13 unknown 78,951 1.71
14 Slurp 69,691 1.51
15 Firefox/3.0.5 41,336 0.89
16 HTTrack 3.0x 39,550 0.86
17 Firefox/2.0.0.17 37,489 0.81
18 FDM 36,741 0.80
19 Opera/9.25 35,988 0.78
20 Firefox/2.0.0.15 32,253 0.70
21 Opera/9.27 29,426 0.64
22 MSIE 5.0 25,430 0.55
23 Firefox/2.0.0.6 24,324 0.53
24 Opera/9.26 22,774 0.49
25 Opera/9.50 22,558 0.49
Sum 4,619,528 100.00

To top of page

Top 25 of 239 operating systems , sorted by number of files

N operating systems times %


1 Windows 1,821,979 39.44
2 Windows NT 5.1 1,639,159 35.48
3 unknown 300,213 6.50
4 Linux i686 256,035 5.54
5 Windows NT 6.0 205,439 4.45
6 Windows NT 5.0 103,653 2.24
7 Windows 98 81,110 1.76
8 Linux x86_64 37,995 0.82
9 Mac OS X 30,584 0.66
10 Windows NT 4.0 18,375 0.40
11 Windows NT 5.2 16,831 0.36
12 Mac OS X 10.5 11,931 0.26
13 Linux 11,615 0.25
14 Linux i686 10,369 0.22
15 Win16 8,062 0.17
Mac OS X
16 7,148 0.15
10_4_11
17 Mac OS X 10_5_5 7,021 0.15
18 Mac OS X Mach-O 6,199 0.13
19 Windows XP 5.1 6,126 0.13
20 Mac OS X 10_5_2 5,696 0.12
21 Mac OS X 10_5_4 5,005 0.11
22 Mac OS X 10.4 3,571 0.08
23 Mac OS X 10_5_3 2,586 0.06
24 Windows 6.0 1,809 0.04
25 Kubuntu 1,469 0.03
Sum 4,619,528 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 139,762 3.03
2 01 100,679 2.18
3 02 82,598 1.79
4 03 75,680 1.64
5 04 77,487 1.68
6 05 75,007 1.62
7 06 82,883 1.79
8 07 116,923 2.53
9 08 154,932 3.35
10 09 194,886 4.22
11 10 221,648 4.80
12 11 250,574 5.42
13 12 256,814 5.56
14 13 256,851 5.56
15 14 262,359 5.68
16 15 263,085 5.70
17 16 258,651 5.60
18 17 256,784 5.56
19 18 255,081 5.52
20 19 254,158 5.50
21 20 265,409 5.75
22 21 272,537 5.90
23 22 249,895 5.41
24 23 194,845 4.22
Sum 4,619,528 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008y.html (2 of 2)1/20/2009 8:04:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2007y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2007

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 212132 IPs and host names , sorted by number of files

N IPs and host names times %


1 217.7.228.75=pd907e44b.dip0.t-ipconnect.de 23,943 0.51
2 217.194.34.103=(not found) 5,000 0.11
65.55.212.136=livebot-65-55-212-136.search.live.
3 4,726 0.10
com
4 212.26.140.12=(not found) 4,517 0.10
5 209.249.86.17=(not found) 4,365 0.09
65.55.212.137=livebot-65-55-212-137.search.live.
6 4,356 0.09
com
7 81.52.143.15=natcrawlbloc01.net.m1.fti.net 4,034 0.09
8 203.128.82.151=ip-82-151.neuviz.net.id 3,976 0.09
9 81.52.143.16=natcrawlbloc03.net.m1.fti.net 3,821 0.08
10 134.147.40.211=(not found) 3,689 0.08
11 194.39.218.10=http-v.fe.bosch.de 3,532 0.08
12 66.249.72.135=crawl-66-249-72-135.googlebot.com 3,528 0.08
13 203.160.1.49=localhost 3,342 0.07
14 87.166.67.160=p57A643A0.dip.t-dialin.net 3,342 0.07
15 202.44.14.194=(not found) 3,196 0.07
16 62.225.37.69=(not found) 3,140 0.07
17 64.208.172.181=xcrawl109.alexa.com 3,137 0.07
18 222.187.125.90=(not found) 3,102 0.07
19 193.2.102.86=(not found) 2,864 0.06
20 217.10.60.85=(not found) 2,812 0.06
21 155.232.128.10=(not found) 2,769 0.06
22 192.109.190.88=vproxy01.bmwgroup.com 2,700 0.06
23 77.120.128.247=ds-nat-128-247.datasvit.net 2,308 0.05
24 65.214.39.180=(not found) 2,269 0.05
25 194.225.236.225=(not found) 2,258 0.05
Sum 4,653,101 100.00

To top of page

Top 25 of 212132 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 65.55.212.137=livebot-65-55-212-137.search.live.com 136,519 0.29
2 65.55.212.136=livebot-65-55-212-136.search.live.com 124,780 0.27
3 203.128.82.151=ip-82-151.neuviz.net.id 115,803 0.25
4 212.26.140.12=(not found) 83,506 0.18
5 194.225.236.225=(not found) 79,148 0.17
6 66.249.72.135=crawl-66-249-72-135.googlebot.com 70,942 0.15
7 203.129.199.98=(not found) 70,554 0.15
122.164.52.71=ABTS-TN-dynamic-071.52.164.122.airtelbroadband.
8 57,536 0.12
in
9 172.182.203.18=ACB6CB12.ipt.aol.com 56,935 0.12
10 217.194.34.103=(not found) 56,800 0.12
11 66.249.66.210=crawl-66-249-66-210.googlebot.com 54,342 0.12
12 194.39.218.10=http-v.fe.bosch.de 52,829 0.11
13 77.120.128.247=ds-nat-128-247.datasvit.net 49,537 0.11
14 220.225.6.74=(not found) 46,193 0.10
15 64.208.172.181=xcrawl109.alexa.com 45,002 0.10
16 217.218.36.126=(not found) 43,842 0.09
17 217.10.60.85=(not found) 40,457 0.09
18 196.219.177.10=host-196.219.177.10.tedata.net 40,058 0.09
19 202.44.14.194=(not found) 37,898 0.08
20 74.6.69.114=wm508841.inktomisearch.com 37,050 0.08
21 74.6.71.241=wm508449.inktomisearch.com 36,644 0.08
22 78.49.23.209=f049023209.adsl.alicedsl.de 36,192 0.08
23 62.225.37.69=(not found) 34,802 0.08
24 83.4.202.116=aahu116.neoplus.adsl.tpnet.pl 34,536 0.07
25 81.52.143.15=natcrawlbloc01.net.m1.fti.net 33,767 0.07
Sum 46,321,840 100.00

To top of page

Top 25 of 41262 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


1 81.52.143.15=natcrawlbloc01.net.m1.fti.net 1,406 0.51
2 81.52.143.16=natcrawlbloc03.net.m1.fti.net 1,350 0.49
3 72.30.61.175=lt100001.inktomisearch.com 1,148 0.42
4 72.30.61.176=lt100002.inktomisearch.com 1,144 0.41
5 65.54.188.99=livebot-65-54-188-99.search.live.com 887 0.32
6 74.6.85.216=ct501244.crawl.yahoo.net 828 0.30
7 193.47.80.44=crawl8.exabot.com 808 0.29
8 74.6.75.20=wm509405.inktomisearch.com 699 0.25
9 209.249.86.17=(not found) 674 0.24
65.54.188.100=livebot-65-54-188-100.search.live.
10 572 0.21
com
11 64.208.172.181=xcrawl109.alexa.com 567 0.20
65.55.208.197=livebot-65-55-208-197.search.live.
12 563 0.20
com
13 65.111.166.195=195-166-111-65.serverpronto.com 544 0.20
14 65.214.45.119=crawler4010.ask.com 507 0.18
65.55.208.210=livebot-65-55-208-210.search.live.
15 504 0.18
com
16 65.54.188.98=livebot-65-54-188-98.search.live.com 499 0.18
17 66.249.66.210=crawl-66-249-66-210.googlebot.com 492 0.18
18 38.99.13.125=crawl-4.cuill.com 476 0.17
65.55.212.136=livebot-65-55-212-136.search.live.
19 463 0.17
com
65.55.208.209=livebot-65-55-208-209.search.live.
20 455 0.16
com
21 66.249.72.135=crawl-66-249-72-135.googlebot.com 452 0.16
22 74.6.75.31=wm509407.inktomisearch.com 450 0.16
65.55.212.137=livebot-65-55-212-137.search.live.
23 426 0.15
com
24 193.252.149.15=natcrawlbloc02.net.s1.fti.net 421 0.15
25 72.30.61.105=lt100005.inktomisearch.com 421 0.15
Sum 276,613 100.00

To top of page

Top 25 of 327 countries of origin , sorted by number of files

N countries of origin times %


1 net 1,217,739 26.17
2 Germany 1,012,428 21.76
3 (unresolved) 848,510 18.24
4 com 342,413 7.36
5 Poland 121,560 2.61
6 Austria 107,030 2.30
7 Switzerland 76,146 1.64
8 Netherlands 69,928 1.50
9 India 45,135 0.97
10 Australia 44,860 0.96
11 Italy 39,123 0.84
12 Indonesia 39,098 0.84
13 Mexico 37,118 0.80
14 Brazil 35,636 0.77
15 Belgium 32,119 0.69
16 Finland 31,541 0.68
17 Czech Republic 31,271 0.67
18 Romania 29,850 0.64
19 Hungary 28,448 0.61
20 edu 28,366 0.61
21 Sweden 28,348 0.61
22 Canada 25,642 0.55
23 Greece 23,437 0.50
24 Lithuania 21,775 0.47
25 United Kingdom 21,187 0.46
Sum 4,653,101 100.00

To top of page

Top 25 of 1379 pathes , sorted by number of files

N pathes times %
1 /common/ 1,546,837 33.24
2 /avr_gra/ 895,620 19.25
3 / 639,260 13.74
4 /avr_en/beginner/ 187,501 4.03
5 /avr_de/beginner/ 186,672 4.01
6 /avr_en/ 160,016 3.44
7 /avr_de/ 152,003 3.27
8 /avr_de/fcount/ 77,689 1.67
9 /avr_en/source/ 61,869 1.33
10 /avr_de/praesentation/ 59,826 1.29
11 /avr_de/quellen/ 48,633 1.05
12 /avr_en/calc/ 43,382 0.93
13 /avr_de/rechteckgen/bilder/ 43,204 0.93
14 /avr_de/rechnen/ 39,365 0.85
15 /avr_en/keypad/ 39,342 0.85
16 /gavrasm/ 36,597 0.79
17 /avr_de/keypad/ 36,310 0.78
18 /avr_en/signalgen/pics/ 33,719 0.72
19 /avr_de/stepper/ 22,510 0.48
/privat/stechlin/rundgang/
20 21,390 0.46
thumbs/
21 /akkuload/ 21,204 0.46
22 /avr_en/stepper/ 17,853 0.38
23 /avr_de/rechteckgen/ 16,247 0.35
/avr_de/praesentation/
24 16,034 0.34
sourcecode/
25 /avr_en/signalgen/ 15,783 0.34
Sum 4,653,101 100.00

To top of page

Top 25 of 1379 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 9,868,009 21.30
2 /avr_gra/ 7,023,325 15.16
3 / 3,547,477 7.66
4 /avr_de/fcount/ 2,970,405 6.41
5 /avr_de/ 2,271,995 4.90
6 /avr_de/intro/pdf/ 2,236,948 4.83
7 /avr_en/ 2,082,457 4.50
8 /avr_de/beginner/ 1,728,807 3.73
9 /avr_en/beginner/ 1,571,272 3.39
10 /gavrasm/v21/ 1,225,225 2.65
/avr_de/rechteckgen/
11 1,159,636 2.50
bilder/
12 /avr_en/signalgen/pics/ 863,762 1.86
13 /avr_de/stepper/ 590,388 1.27
14 /avr_en/signalgen/ 587,111 1.27
15 /common/ 574,097 1.24
16 /avr_de/rechteckgen/ 536,429 1.16
17 /akkuload/ 522,947 1.13
18 /avr_en/calc/ 442,277 0.95
19 /avr_en/stepper/ 435,317 0.94
20 /avr_de/rechnen/ 391,766 0.85
21 /avr_de/intro/ppt/ 357,156 0.77
22 /weblox_de/ 326,276 0.70
23 /avr_en/source/ 288,069 0.62
24 /avr_en/keypad/ 285,014 0.62
25 /weblox_en/ 278,093 0.60
Sum 46,321,840 100.00

To top of page

Top 25 of 6501 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 286,286 6.15
2 /avr_gra/RingLogo.jpg 141,346 3.04
/common/knowhow.
3 115,313 2.48
gif
4 /common/r2r.gif 114,850 2.47
5 /common/clock.gif 114,848 2.47
6 /common/app.gif 114,828 2.47
7 /avr_gra/stk_lcd.jpg 114,704 2.47
8 /common/gavrasm.gif 114,689 2.46
9 /common/example.gif 114,603 2.46
10 /common/hardware.gif 114,511 2.46
11 /common/akkuload.gif 114,477 2.46
12 /common/beginner.gif 114,361 2.46
/common/gavrasmw.
13 114,171 2.45
gif
14 /common/calc.gif 114,079 2.45
15 /common/keyb.gif 114,025 2.45
16 /common/adc.gif 113,916 2.45
17 /index.html 86,602 1.86
18 /avr_2313.gif 67,726 1.46
19 /dg4fac.gif 67,623 1.45
20 /avr-asm-tutorial.gif 67,356 1.45
21 /avr_en/index.html 65,937 1.42
22 /avr_de/index.html 63,917 1.37
23 /common/tn13.gif 58,155 1.25
24 /avr_gra/2313.gif 55,031 1.18
25 /robots.txt 39,664 0.85
Sum 4,653,101 100.00

To top of page

Top 25 of 6501 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 3,601,017 7.77
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 1,919,457 4.14
3 /avr_de/index.html 1,373,544 2.97
4 /avr_en/index.html 1,295,519 2.80
5 /avr_2313.gif 1,168,346 2.52
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 956,522 2.06
pdf
7 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 894,641 1.93
8 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 780,206 1.68
9 /dg4fac.gif 700,084 1.51
10 /avr_gra/pwm_simul.jpg 694,191 1.50
11 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 691,134 1.49
12 /avr_de/fcount/dscf0004.jpg 587,196 1.27
13 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 569,355 1.23
14 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 532,731 1.15
15 /avr_de/fcount/dscf0005.jpg 507,021 1.09
16 /avr_gra/r2r_hardware.jpg 503,710 1.09
17 /avr_de/fcount/dscf0001.jpg 476,691 1.03
18 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 460,301 0.99
19 /index.html 453,169 0.98
20 /avr_gra/exp2313.gif 434,362 0.94
21 /Akkulader_Beschreibung.pdf 424,180 0.92
22 /akkuload/dscf0030s.jpg 401,435 0.87
23 /avr_en/signalgen/pics/rectgen_wiring.jpg 394,018 0.85
24 /favicon.ico 390,057 0.84
25 /avr_de/praesentation/Teil_3_Befehle.pdf 387,428 0.84
Sum 46,321,840 100.00

To top of page

Top 25 of 3456 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 86,602 8.36
2 /avr_en/index.html 65,937 6.37
3 /avr_de/index.html 63,917 6.17
4 /avr_en/beginner/RIGHT.html 30,998 2.99
5 /avr_en/beginner/index.html 30,941 2.99
6 /avr_en/beginner/LEFT.html 30,632 2.96
7 /avr_de/beginner/rechts.html 29,012 2.80
8 /avr_de/beginner/links.html 28,554 2.76
9 /avr_de/beginner/index.html 28,368 2.74
/avr_en/beginner/HARDWARE.
10 14,506 1.40
html
11 /avr_de/beginner/hardware.html 11,872 1.15
12 /avr_en/beginner/REGISTER.html 10,405 1.00
13 /avr_en/AVR_TUT.html 10,073 0.97
14 /avr_de/praesentation/index.html 9,885 0.95
15 /avr_de/beginner/register.html 9,572 0.92
16 /avr_de/beginner/werkzeuge.html 9,493 0.92
17 /avr_de/beginner/sprung.html 9,376 0.91
18 /avr_en/beginner/JUMP.html 8,987 0.87
19 /avr_en/AVR_ADC500.html 8,694 0.84
20 /avr_en/AVR_DAC.html 8,364 0.81
21 /avr_de/beginner/ports.html 8,302 0.80
22 /avr_en/beginner/TOOLS.html 8,297 0.80
23 /avr_de/avr_tut.html 8,181 0.79
24 /avr_en/keypad/keyboard.html 8,098 0.78
25 /avr_de/avr_dac.html 7,982 0.77
Sum 1,035,482 100.00

To top of page

Top 25 of 3456 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 1,373,544 12.19
2 /avr_en/index.html 1,295,519 11.50
3 /index.html 453,169 4.02
4 /avr_de/beginner/sprung.html 253,135 2.25
5 /avr_de/dcf77uhr.html 229,451 2.04
6 /avr_en/beginner/RIGHT.html 216,454 1.92
7 /avr_en/beginner/JUMP.html 207,488 1.84
8 /avr_de/beginner/rechts.html 197,504 1.75
9 /avr_de/beginner/rechnen.html 188,178 1.67
10 /avr_en/keypad/keyboard.html 159,099 1.41
11 /avr_de/keypad/keyboard.html 152,722 1.36
12 /avr_en/beginner/CALC.html 151,505 1.34
/avr_de/rechteckgen/rectgen_m8.
13 150,899 1.34
html
14 /avr_de/beginner/pdetail.html 141,984 1.26
15 /avr_en/beginner/LEFT.html 136,621 1.21
16 /avr_en/AVR_ADC500.html 134,904 1.20
17 /avr_de/beginner/commands.html 131,123 1.16
18 /avr_de/avr_dac.html 130,890 1.16
19 /avr_en/beginner/PDETAIL.html 125,277 1.11
20 /avr_de/beginner/links.html 124,240 1.10
21 /avr_en/beginner/REGISTER.html 121,073 1.07
22 /avr_en/AVR_DAC.html 120,039 1.07
23 /avr_en/signalgen/rectgen_m8.html 110,132 0.98
24 /avr_de/beginner/werkzeuge.html 108,642 0.96
/avr_en/beginner/COMMANDS.
25 108,275 0.96
html
Sum 11,265,035 100.00

To top of page

Top 25 of 969 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 141,321 19.58
2 /avr_gra/stk_lcd.jpg 114,698 15.89
3 /avr_gra/8515.jpg 24,887 3.45
4 /avr_gra/avr_isp.jpg 24,507 3.39
5 /avr_gra/exp2313g.jpg 24,431 3.38
6 /avr_gra/exp_2313.jpg 24,278 3.36
7 /avr_gra/r2r_sawtooth.jpg 19,256 2.67
8 /avr_gra/r2r_wave.jpg 18,511 2.56
9 /avr_gra/AT90S8515.jpg 16,745 2.32
10 /avr_gra/r2r_sawtoothupperbound.jpg 14,854 2.06
11 /avr_gra/r2r_hardware.jpg 14,411 2.00
12 /avr_gra/r2r_triangle.jpg 14,303 1.98
13 /avr_gra/r2r_sawtooth741.jpg 14,153 1.96
14 /avr_gra/r2r_upperbound.jpg 14,097 1.95
15 /avr_gra/pwm_simul.jpg 12,655 1.75
16 /avr_gra/adc8conn.jpg 12,593 1.74
17 /avr_gra/apps.jpg 12,099 1.68
18 /akkuload/dscf0030s.jpg 10,111 1.40
19 /avr_de/praesentation/zuendtester.jpg 9,195 1.27
/avr_de/rechteckgen/bilder/rectgen_280.
20 9,176 1.27
jpg
21 /avr_en/signalgen/pics/rectgen_280.jpg 7,583 1.05
22 /avr_gra/stk200lcd.jpg 7,488 1.04
23 /avr_gra/stk200.jpg 7,304 1.01
24 /avr_de/fcount/fcount_sm.jpg 7,207 1.00
25 /avr_gra/stk_ram.jpg 6,782 0.94
Sum 721,901 100.00

To top of page

Top 25 of 704 GIF-files , sorted by number of files

N GIF-files times %
1 /common/knowhow.gif 115,311 4.98
2 /common/clock.gif 114,845 4.96
3 /common/r2r.gif 114,845 4.96
4 /common/app.gif 114,825 4.96
5 /common/gavrasm.gif 114,686 4.96
6 /common/example.gif 114,600 4.95
7 /common/hardware.gif 114,506 4.95
8 /common/akkuload.gif 114,471 4.95
9 /common/beginner.gif 114,359 4.94
10 /common/gavrasmw.gif 114,167 4.93
11 /common/calc.gif 114,076 4.93
12 /common/keyb.gif 114,023 4.93
13 /common/adc.gif 113,913 4.92
14 /avr_2313.gif 67,722 2.93
15 /dg4fac.gif 67,612 2.92
16 /avr-asm-tutorial.gif 67,355 2.91
17 /common/tn13.gif 58,153 2.51
18 /avr_gra/2313.gif 55,013 2.38
19 /avr_gra/exp2313.gif 25,231 1.09
20 /avr_gra/avr_isp.gif 24,534 1.06
21 /avr_gra/isp10pin.gif 24,311 1.05
22 /avr_gra/isp6pin.gif 24,305 1.05
23 /avr_gra/screenshot.gif 22,787 0.98
24 /avr_gra/r2r.gif 14,585 0.63
/avr_gra/r2r_buffered.
25 14,371 0.62
gif
Sum 2,314,038 100.00

To top of page

Top 25 of 422 entry pages , sorted by number of files

N entry pages times %


1 /index.html 33,361 19.51
2 /avr_en/index.html 17,634 10.31
3 /avr_de/index.html 15,829 9.26
4 /avr_de/beginner/index.html 5,980 3.50
5 /avr_en/beginner/index.html 5,439 3.18
6 /avr_en/beginner/HARDWARE.html 3,636 2.13
7 /avr_en/AVR_DAC.html 3,549 2.08
8 /avr_de/avr_dac.html 3,446 2.02
9 /privat/stechlin/index.html 2,949 1.72
/avr_de/rechteckgen/rectgen_m8.
10 2,878 1.68
html
11 /avr_de/fcount/fcount_m8.html 2,823 1.65
12 /avr_de/rechnen/konversion.html 2,532 1.48
13 /avr_de/beginner/hardware.html 2,393 1.40
14 /avr_de/keypad/keyboard.html 2,140 1.25
15 /avr_en/AVR_ADC500.html 2,078 1.22
16 /akkuload/de/index.html 1,967 1.15
17 /avr_de/beginner/werkzeuge.html 1,940 1.13
18 /avr_de/avr_adc500.html 1,641 0.96
19 /avr_en/keypad/keyboard.html 1,639 0.96
20 /avr_en/signalgen/rectgen_m8.html 1,558 0.91
21 /avr_de/beginner/rechnen.html 1,549 0.91
22 /avr_de/rechnen/index.html 1,355 0.79
23 /avr_en/calc/CONVERSION.html 1,348 0.79
24 /avr_de/beginner/pdetail.html 1,312 0.77
25 /avr_de/lcd4_500.html 1,290 0.75
Sum 171,011 100.00

To top of page

Top 25 of 609 cheat pages , sorted by number of files

N cheat pages times %


1 20,576 9.70
2 /index.html 18,897 8.91
3 /avr_en/index.html 14,434 6.80
4 /avr_de/index.html 14,261 6.72
5 /avr_en/beginner/HARDWARE.html 4,540 2.14
6 /avr_de/beginner/rechts.html 4,453 2.10
7 /avr_en/beginner/RIGHT.html 3,972 1.87
8 /avr_en/AVR_DAC.html 3,962 1.87
9 /avr_de/avr_dac.html 3,830 1.81
10 /avr_de/beginner/hardware.html 3,407 1.61
11 /privat/stechlin/index.html 3,040 1.43
12 /avr_de/keypad/keyboard.html 2,938 1.38
13 /avr_de/fcount/fcount_m8.html 2,930 1.38
14 /akkuload/de/index.html 2,873 1.35
15 /avr_en/AVR_ADC500.html 2,641 1.24
/avr_de/rechteckgen/rectgen_m8.
16 2,622 1.24
html
17 /avr_en/keypad/keyboard.html 2,549 1.20
18 /avr_de/beginner/werkzeuge.html 2,546 1.20
19 /avr_de/beginner/rechnen.html 2,336 1.10
20 /avr_de/beginner/sprung.html 2,245 1.06
21 /avr_de/praesentation/index.html 2,099 0.99
22 /avr_de/avr_adc500.html 1,923 0.91
23 /avr_de/rechnen/konvert.html 1,917 0.90
24 /avr_de/rechnen/konversion.html 1,861 0.88
25 /avr_en/beginner/REGISTER.html 1,857 0.88
Sum 212,132 100.00

To top of page

Top 25 of 338 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 80,210 14.26
2 /avr_en/index.html 68,661 12.20
3 /avr_en/beginner/index.html 57,168 10.16
4 /avr_de/beginner/index.html 51,599 9.17
5 / 40,317 7.17
6 /avr_en/beginner/RIGHT.html 26,107 4.64
7 /avr_de/beginner/rechts.html 24,597 4.37
8 /avr_de/beginner/links.html 22,246 3.95
9 /avr_en/beginner/LEFT.html 21,330 3.79
10 /sitemap_en.html 15,763 2.80
11 /sitemap_de.html 15,666 2.78
12 /avr_de/apps.html 8,625 1.53
13 /index.html 8,223 1.46
14 /avr_en/AVR_TUT.html 7,950 1.41
15 /avr_en/ 6,287 1.12
16 /avr_de/avr_tut.html 5,933 1.05
17 /avr_en/calc/index.html 5,658 1.01
18 /avr_en/APPS.html 5,489 0.98
19 /avr_de/rechnen/index.html 5,417 0.96
20 /avr_de/ 4,647 0.83
21 /avr_de/beginner/commands.html 3,654 0.65
22 /weblox_de/index.html 3,423 0.61
23 /weblox_en/index.html 3,165 0.56
/avr_de/rechteckgen/rectgen_m8.
24 2,482 0.44
html
25 /avr_en/signalgen/rectgen_m8.html 2,469 0.44
Sum 562,579 100.00

To top of page

Top 25 of 6441 external referrers , sorted by number of files

N external referrers times %


1 - 235,695 81.43
2 http://r.webring.com/hub?ring=avr 3,149 1.09
3 http://www.mikrocontroller.net/articles/AVR 1,996 0.69
4 http://avr-asm.tripod.com/ 1,001 0.35
5 http://de.wikipedia.org/wiki/Atmel_AVR 968 0.33
6 http://www.dg4fac.de/linksunten.html 938 0.32
7 http://www.mikrocontroller.net/articles/Linksammlung 934 0.32
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
8 839 0.29
kurs.htm
9 http://de.wikipedia.org/wiki/R2R-Netzwerk 817 0.28
10 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 807 0.28
11 http://www.rowalt.de/mc/avr/linksd.htm 807 0.28
12 http://www.serasidis.gr/links.htm 761 0.26
13 http://www.dg4fac.de/rechtsunten.html 724 0.25
14 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 519 0.18
http://electrons.psychogenic.com/modules/arms/art/3/
15 AVRGCCProgrammingG 494 0.17
uide.php
16 http://frank.bol.ucla.edu/avr.htm 490 0.17
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
17 487 0.17
ESC_by1_bz0_bs0.html
18 http://www.edw.com.pl/ea/asm_avr_jezyk.html 472 0.16
19 http://www.dg4fac.de/stechlin/ 419 0.14
20 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 409 0.14
http://www.avrfreaks.net/index.php?module=Freaks%
21 20Academy&func=viewIt 408 0.14
em&item_id=355&item_type=project
http://www.avrfreaks.net/index.php?
22 name=PNphpBB2&file=viewtopic&t=3698 399 0.14
8
23 http://aquarius.ime.eb.br/~pinho/micro/index.html 398 0.14
24 http://www.informatik.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 377 0.13
25 http://www.raw.to/rubriken/private_elektronik.html 372 0.13
Sum 289,459 100.00

To top of page

Top 25 of 585 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 77,224 44.91
2 http://www.google.com 29,915 17.40
3 http://www.google.at 5,901 3.43
4 http://www.google.co.in 3,880 2.26
5 http://www.google.ch 3,579 2.08
6 http://www.google.pl 3,024 1.76
7 http://www.google.co.uk 2,771 1.61
8 http://www.google.ca 2,437 1.42
9 http://www.google.nl 2,244 1.31
10 http://www.google.com.au 2,240 1.30
11 http://search.yahoo.com 2,114 1.23
12 http://www.google.se 1,583 0.92
13 http://www.google.co.id 1,568 0.91
14 http://www.google.fi 1,499 0.87
15 http://www.google.it 1,373 0.80
16 http://www.google.ro 1,269 0.74
http://www.google.com.
17 1,130 0.66
mx
18 http://www.google.com.vn 1,075 0.63
19 http://www.google.be 967 0.56
20 http://www.google.hu 956 0.56
21 http://www.google.cz 943 0.55
http://de.search.yahoo.
22 938 0.55
com
23 http://www.google.com.br 842 0.49
24 http://www.google.fr 817 0.48
25 http://www.google.gr 776 0.45
Sum 171,954 100.00

To top of page

Top 25 of 73701 search strings , sorted by number of files

N search strings times %


1 avr tutorial 4,459 2.59
2 avr 3,405 1.98
3 avr assembler 2,203 1.28
4 assembler 2,155 1.25
5 assembler tutorial 1,888 1.10
6 atmega8 1,139 0.66
7 avr programming 1,002 0.58
8 AVR 999 0.58
9 attiny13 906 0.53
10 avrtutorial 775 0.45
11 avr asm 739 0.43
12 stk500 670 0.39
13 avr assembly 646 0.38
14 AVR tutorial 567 0.33
avr assembler
15 493 0.29
tutorial
16 atmel tutorial 486 0.28
17 Assembler 476 0.28
18 avr asm tutorial 473 0.28
19 atmega16 433 0.25
20 gavrasm 423 0.25
21 assembler lernen 399 0.23
22 mikrokontroller 380 0.22
23 asm tutorial 377 0.22
24 atmel avr 374 0.22
25 wavrasm 351 0.20
Sum 171,954 100.00

To top of page

Top 14 of 14 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 4,047,395 86.98
2 304 Not changed 541,700 11.64
3 206 Partial information 31,426 0.68

http://www.avr-asm-tutorial.net/weblox_en/2007y.html (1 of 2)1/20/2009 8:04:29 PM


Weblog statistic for http://www.avr-asm-tutorial.net

4 404 File not found 21,824 0.47


5 301 Permanently moved 7,783 0.17
6 403 Forbidden 1,577 0.03
7 300 Multiple choices 1,224 0.03
8 405 Method not allowed 109 0.00
9 400 Error in request 21 0.00
10 xxx Unknown error 20 0.00
11 xxx Unknown error 18 0.00
12 501 Not implemented 2 0.00
13 xxx Unknown error 1 0.00
14 401 Not authorized 1 0.00
Sum 4,653,101 100.00

To top of page

Top 25 of 3099 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 1,727 7.91
2 /beginner_de.pdf 1,469 6.73
3 /favicon.ico 1,024 4.69
4 /gavrasm/v16/instr.asm 729 3.34
5 /avr_en/quellen/schrittmotor_v1.asm 671 3.07
6 /gavrasm/v16/DosRead.Txt 618 2.83
7 /avr_en/stepper/schrittmotor_v1.html 584 2.68
8 /gavrasm/v16/ReadMe.Txt 497 2.28
9 /avr_de/beginner/portdetail.html 462 2.12
10 /gavrasm/v16/gavrasm_sources_lin.zip 417 1.91
11 /gavrasm/v16/gavrasm_sources_doswin.zip 413 1.89
12 /gavrasm/v16/LiesMich.Txt 389 1.78
13 /gavrasm/v16/gavrasm_lin_en.zip 376 1.72
14 /gavrasm/v16/gavrasm_dos_en.zip 376 1.72
15 /_vti_inf.html 363 1.66
16 /gavrasm/v16/gavrasm_win_en.zip 320 1.47
/MSOffice/cltreq.asp?
17 259 1.19
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
18 /gavrasm/v16/gavrasm_win_de.zip 253 1.16
19 /gavrasm/v16/gavrasm_lin_de.zip 244 1.12
20 /gavrasm/v16/gavrasm_dos_de.zip 238 1.09
21 /avr_en/index.html 197 0.90
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
22 %20la 196 0.90
nguage_files/LEFT.htm
23 /robots.txt 196 0.90
24 /avr_de/index.html 177 0.81
25 /avr_de/intro/ppt/beispiel10_snd.wav 122 0.56
Sum 21,824 100.00

To top of page

Top 25 of 1043 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 2,133,649 45.85
2 Mozilla/5.0 2,083,460 44.78
3 Opera/9.10 57,224 1.23
4 Mozilla/4.5 41,506 0.89
5 Opera/9.23 27,048 0.58
6 Opera/9.21 25,996 0.56
7 Opera/9.20 25,942 0.56
8 Opera/9.02 23,272 0.50
9 msnbot/1.0 20,544 0.44
10 Opera/9.24 19,579 0.42
11 Opera/9.01 18,914 0.41
12 Opera/9.22 15,225 0.33
msnbot-
13 13,320 0.29
media/1.0
14 - 10,897 0.23
15 Opera/9.00 9,120 0.20
16 Wget/1.10.2 5,378 0.12
17 Microsoft 5,373 0.12
18 Mozilla/3.01 3,909 0.08
19 ia_archiver 3,876 0.08
20 Xaldon 3,624 0.08
21 WebZIP/4.1 3,504 0.08
22 FDM 2.x 3,148 0.07
23 FAST 3,026 0.07
24 West 3,008 0.06
25 Opera/9.25 2,877 0.06
Sum 4,653,101 100.00

To top of page

Top 25 of 1646 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 1,332,020 28.63
2 MSIE 7.0 634,391 13.63
3 Firefox/2.0.0.3 268,128 5.76
4 Firefox/2.0.0.6 180,089 3.87
5 Firefox/2.0.0.1 175,411 3.77
6 Firefox/2.0.0.4 174,869 3.76
7 Firefox/2.0.0.7 113,002 2.43
8 Firefox/2.0.0.11 112,603 2.42
9 Firefox/2.0.0.9 104,693 2.25
10 Firefox/2.0.0.2 99,731 2.14
11 unknown 82,487 1.77
12 Slurp 75,991 1.63
13 Firefox/1.5.0.9 69,175 1.49
14 Firefox/2.0.0.8 65,456 1.41
15 Gecko 61,506 1.32
16 Firefox/2.0 57,860 1.24
17 Opera/9.10 56,850 1.22
18 Firefox/2.0.0.5 49,121 1.06
19 Firefox/1.5.0.11 47,943 1.03
20 MSIE 5.0 41,472 0.89
21 HTTrack 3.0x 39,931 0.86
22 Firefox/1.5.0.12 37,485 0.81
23 FDM 36,940 0.79
24 Firefox/1.5.0.10 28,184 0.61
25 Opera/9.23 26,736 0.57
Sum 4,653,101 100.00

To top of page

Top 25 of 185 operating systems , sorted by number of files

N operating systems times %


1 Windows NT 5.1 1,909,514 41.04
2 Windows 1,653,900 35.54
3 unknown 288,039 6.19
4 Linux i686 219,217 4.71
5 Windows NT 5.0 184,244 3.96
6 Windows 98 131,482 2.83
7 Windows NT 6.0 79,202 1.70
8 Macintosh 59,401 1.28
9 Windows NT 4.0 23,942 0.51
10 Windows NT 5.2 17,627 0.38
11 Linux 17,311 0.37
12 Linux x86_64 16,366 0.35
13 Linux i686 11,378 0.24
14 Kubuntu 6,369 0.14
15 Windows XP 5.1 4,025 0.09
16 Windows 95 3,874 0.08
17 Win32 2,854 0.06
18 Windows NT 2,572 0.06
19 FreeBSD i386 2,342 0.05
20 SunOS sun4u 2,077 0.04
21 FreeBSD 1,964 0.04
22 SunOS 5.6 sun4u 1,500 0.03
23 Linux i586 1,432 0.03
24 Windows XP 1,255 0.03
25 Windows ME 1,105 0.02
Sum 4,653,101 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 144,230 3.10
2 01 104,195 2.24
3 02 82,582 1.77
4 03 74,946 1.61
5 04 72,963 1.57
6 05 72,699 1.56
7 06 82,830 1.78
8 07 114,089 2.45
9 08 157,321 3.38
10 09 191,668 4.12
11 10 224,307 4.82
12 11 243,967 5.24
13 12 252,424 5.42
14 13 257,068 5.52
15 14 272,603 5.86
16 15 274,391 5.90
17 16 271,710 5.84
18 17 263,141 5.66
19 18 252,712 5.43
20 19 256,960 5.52
21 20 269,236 5.79
22 21 272,504 5.86
23 22 247,083 5.31
24 23 197,472 4.24
Sum 4,653,101 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2007y.html (2 of 2)1/20/2009 8:04:29 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2006y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2006

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 233805 IPs and host names , sorted by number of files

N IPs and host names times %


1 203.160.1.42=localhost 7,665 0.18
2 80.132.20.174=p508414AE.dip0.t-ipconnect.de 4,704 0.11
3 62.21.81.21=c81-21.icpnet.pl 3,819 0.09
4 202.83.169.98=ntc.net.pk 3,297 0.08
5 66.249.66.111=crawl-66-249-66-111.googlebot.com 3,172 0.07
6 83.245.48.54=83-245-48-54-adsl.dcomms.net 2,951 0.07
7 213.25.33.100=(not found) 2,823 0.07
8 222.124.158.8=(not found) 2,778 0.07
9 217.10.60.85=origin.infineon.com 2,776 0.07
10 194.39.218.10=http-v.fe.bosch.de 2,741 0.06
11 195.251.223.163=(not found) 2,573 0.06
12 203.162.3.147=proxy03-hcm.vnn.vn 2,543 0.06
13 86.120.164.50=(not found) 2,478 0.06
14 66.249.65.179=crawl-66-249-65-179.googlebot.com 2,429 0.06
15 217.219.49.1=(not found) 2,302 0.05
16 83.102.241.162=(not found) 2,287 0.05
17 86.106.64.149=(not found) 2,162 0.05
18 203.160.1.40=localhost 2,051 0.05
19 82.210.249.9=gate12.hella.com 2,010 0.05
20 84.44.159.15=xdsl-84-44-159-15.netcologne.de 1,926 0.05
65.54.188.103=livebot-65-54-188-103.search.live.
21 1,905 0.04
com
22 66.249.66.116=crawl-66-249-66-116.googlebot.com 1,876 0.04
23 203.162.3.145=proxy01-hcm.vnn.vn 1,768 0.04
24 203.162.3.160=(not found) 1,748 0.04
25 217.54.167.32=(not found) 1,744 0.04
Sum 4,257,036 100.00

To top of page

Top 25 of 233805 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 81.169.145.11=bigip-fo.rzone.de 364,082 0.66
2 203.160.1.42=localhost 149,965 0.27
3 80.132.20.174=p508414AE.dip0.t-ipconnect.de 105,564 0.19
4 222.124.158.8=(not found) 92,152 0.17
5 202.83.169.98=ntc.net.pk 85,683 0.16
6 68.142.249.48=lj2038.inktomisearch.com 73,168 0.13
7 84.44.159.15=xdsl-84-44-159-15.netcologne.de 72,371 0.13
8 83.16.153.173=afx173.internetdsl.tpnet.pl 65,313 0.12
9 202.65.112.43=202-65-112-43.jogja.citra.net.id 64,012 0.12
10 194.39.218.10=http-v.fe.bosch.de 58,970 0.11
11 66.249.65.179=crawl-66-249-65-179.googlebot.com 56,736 0.10
12 86.106.64.149=(not found) 52,708 0.10
13 217.194.34.123=erlm514x.erlm.siemens.de 51,170 0.09
14 62.60.183.12=(not found) 50,119 0.09
15 141.32.44.90=proxy1.hrz.fh-zwickau.de 47,693 0.09
16 172.174.156.49=ACAE9C31.ipt.aol.com 47,196 0.09
203.130.243.217=217.subnet243.astinet.telkom.net.
17 46,948 0.09
id
18 217.10.60.85=origin.infineon.com 46,176 0.08
19 86.104.171.16=(not found) 44,982 0.08
20 217.54.167.32=(not found) 44,958 0.08
21 172.141.99.12=AC8D630C.ipt.aol.com 41,717 0.08
22 203.162.3.160=(not found) 40,842 0.07
23 194.225.80.142=(not found) 39,043 0.07
24 217.219.210.3=(not found) 38,520 0.07
25 217.133.221.162=217-133-221-162.b2b.tiscali.it 36,982 0.07
Sum 54,911,375 100.00

To top of page

Top 25 of 43433 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


1 202.108.11.106=(not found) 825 0.32
2 65.214.44.150=egspd42205.ask.com 797 0.31
3 65.54.188.99=msnbot.msn.com 696 0.27
4 65.54.188.100=msnbot.msn.com 686 0.27
65.54.188.103=livebot-65-54-188-103.search.live.
5 644 0.25
com
6 64.242.88.50=sv-crawlfw3.looksmart.com 622 0.24
7 66.154.102.144=www.gigablast.com 536 0.21
8 68.142.251.132=lz321620.inktomisearch.com 526 0.20
65.54.188.102=livebot-65-54-188-102.search.live.
9 507 0.20
com
10 65.54.188.98=livebot-65-54-188-98.search.live.com 505 0.20
11 68.142.251.130=lj2520.inktomisearch.com 479 0.19
65.54.188.101=livebot-65-54-188-101.search.live.
12 475 0.18
com
13 66.249.65.179=crawl-66-249-65-179.googlebot.com 472 0.18
14 74.6.74.198=lj612569.inktomisearch.com 462 0.18
15 64.242.88.60=sv-crawlfw4.looksmart.com 421 0.16
16 193.252.118.101=fwbg2bibae01-vlan3501.woo 411 0.16
17 193.47.80.44=crawl8.exabot.com 399 0.15
18 195.93.21.2=cache-los-aa02.proxy.aol.com 374 0.15
19 68.142.251.133=lz321621.inktomisearch.com 373 0.14
20 68.142.251.86=lj2476.inktomisearch.com 370 0.14
21 68.142.251.129=lz321617.inktomisearch.com 334 0.13
22 72.30.102.139=lj601288.inktomisearch.com 333 0.13
23 69.51.195.62=ip062.195-51-69.Sogetel.net 307 0.12
24 66.154.103.166=www.gigablast.com 303 0.12
25 195.93.60.104=cache-frr-ad08.proxy.aol.com 300 0.12
Sum 257,923 100.00

To top of page

Top 25 of 343 countries of origin , sorted by number of files

N countries of origin times %


1 net 1,014,719 23.84
2 Germany 926,106 21.75
3 (unresolved) 748,833 17.59
4 com 390,196 9.17
5 Poland 119,484 2.81
6 Austria 105,157 2.47
7 Switzerland 70,022 1.64
8 Netherlands 65,468 1.54
9 Australia 40,662 0.96
10 Italy 34,066 0.80
11 Brazil 33,833 0.79
12 Sweden 33,075 0.78
13 Romania 31,044 0.73
14 Hungary 30,891 0.73
15 Canada 30,325 0.71
16 Czech Republic 30,011 0.70
17 edu 28,690 0.67
18 Belgium 28,134 0.66
19 India 27,545 0.65
20 Finland 27,543 0.65
21 Mexico 26,890 0.63
22 Greece 25,477 0.60
23 Indonesia 25,362 0.60
24 United Kingdom 21,251 0.50
25 Lithuania 19,647 0.46
Sum 4,257,036 100.00

To top of page

Top 25 of 1230 pathes , sorted by number of files

N pathes times %
1 /common/ 1,445,085 33.95
2 /avr_gra/ 962,672 22.61
3 / 539,161 12.67
4 /avr_en/beginner/ 172,095 4.04
5 /avr_de/beginner/ 167,541 3.94
6 /avr_en/ 160,934 3.78
7 /avr_de/ 156,331 3.67
8 /avr_en/source/ 66,878 1.57
9 /avr_de/quellen/ 52,114 1.22
10 /avr_en/calc/ 46,999 1.10
11 /avr_de/praesentation/ 42,789 1.01
12 /avr_de/rechnen/ 42,291 0.99
13 /gavrasm/ 37,152 0.87
14 /avr_de/fcount/ 34,293 0.81
15 /avr_de/keypad/ 27,415 0.64
16 /avr_en/keypad/ 24,346 0.57
17 /akkuload/ 23,762 0.56
18 /avr_de/rechteckgen/bilder/ 20,340 0.48
19 /cq-dl/teil3/ 18,895 0.44
20 /avr_en/signalgen/pics/ 18,679 0.44
21 /cq-dl/teil4/ 17,790 0.42
22 /cq-dl/teil1/ 17,368 0.41
23 /akkuload/de/ 16,048 0.38
24 /akkuload/en/ 13,065 0.31
/avr_de/praesentation/
25 11,338 0.27
sourcecode/
Sum 4,257,036 100.00

To top of page

Top 25 of 1230 pathes , sorted by kbytes

N pathes kbytes %
1 / 22,112,913 40.27
2 /avr_gra/ 6,914,932 12.59
3 /avr_de/praesentation/ 6,757,584 12.31
4 /avr_de/ 2,184,220 3.98
5 /avr_en/ 1,987,063 3.62
6 /avr_de/beginner/ 1,617,267 2.95
7 /avr_en/beginner/ 1,427,841 2.60
8 /avr_de/fcount/ 1,291,066 2.35
9 /avr_de/intro/pdf/ 1,032,049 1.88
10 /akkuload/ 580,508 1.06
/avr_de/rechteckgen/
11 542,314 0.99
bilder/
12 /common/ 533,149 0.97
13 /avr_en/calc/ 514,566 0.94
14 /avr_en/signalgen/pics/ 486,209 0.89
15 /avr_de/rechnen/ 437,327 0.80
16 /weblox_de/ 426,564 0.78
17 /weblox_en/ 386,609 0.70
18 /avr_en/signalgen/ 381,507 0.69
19 /gavrasm/v16/ 331,940 0.60
20 /avr_de/rechteckgen/ 305,201 0.56
21 /avr_en/source/ 291,154 0.53
22 /cq-dl/teil4/ 288,748 0.53
23 /gavrasm/gavrasmw/ 271,286 0.49
24 /gavrasm/v17/ 269,342 0.49
25 /gavrasm/v20/ 262,204 0.48
Sum 54,911,375 100.00

To top of page

Top 25 of 4935 requested files , sorted by number of files

N requested files times %


1 /avr_gra/RingLogo.jpg 140,352 3.30
2 /favicon.ico 140,187 3.29
/common/knowhow.
3 110,681 2.60
gif
4 /common/akkuload.gif 110,565 2.60
5 /common/app.gif 110,532 2.60
6 /common/r2r.gif 110,383 2.59
7 /avr_gra/stk_lcd.jpg 110,176 2.59
8 /common/gavrasm.gif 110,082 2.59
9 /common/example.gif 109,961 2.58
10 /common/clock.gif 109,946 2.58
11 /common/beginner.gif 109,908 2.58
/common/gavrasmw.
12 109,727 2.58
gif
13 /common/calc.gif 109,668 2.58
14 /common/hardware.gif 109,666 2.58
15 /common/adc.gif 109,428 2.57
16 /index.html 89,140 2.09
17 /common/keyb.gif 85,251 2.00
18 /avr_gra/r2r_sine.jpg 78,189 1.84
19 /avr_2313.gif 71,329 1.68
20 /dg4fac.gif 71,146 1.67
21 /avr-asm-tutorial.gif 70,925 1.67
22 /avr_en/index.html 64,806 1.52
23 /avr_de/index.html 64,196 1.51
24 /avr_gra/2313.gif 46,716 1.10
25 /common/tn13.gif 39,277 0.92
Sum 4,257,036 100.00

To top of page

Top 25 of 4935 requested files , sorted by kbytes

N requested files kbytes %


1 /beginner_en.pdf 7,201,599 13.11
2 /beginner_de.pdf 5,028,900 9.16
3 /Akkulader_Beschreibung.pdf 3,111,167 5.67
4 /avr_de/praesentation/Anwendungsbeispiele.pdf 2,629,969 4.79
5 /avr_en.zip 2,462,057 4.48
6 /avr_de/index.html 1,265,527 2.30
7 /avr_de.zip 1,256,923 2.29
8 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 1,216,846 2.22
9 /avr_2313.gif 1,208,775 2.20
10 /avr_en/index.html 1,188,483 2.16
11 /avr_gra/pwm_simul.jpg 729,171 1.33
12 /dg4fac.gif 724,135 1.32
/avr_de/praesentation/Teil_5b_Beispiel01_02.
13 629,291 1.15
pdf
14 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 618,616 1.13
15 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 517,794 0.94
16 /avr_gra/exp2313.gif 475,478 0.87
17 /index.html 458,247 0.83
18 /akkuload/dscf0030s.jpg 445,460 0.81
19 /avr_gra/r2r_hardware.jpg 407,976 0.74
20 /avr_gra/exp2313g.jpg 362,915 0.66
21 /avr_gra/stk_lcd.jpg 355,377 0.65
22 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 348,547 0.63
23 /avr_gra/2313.gif 316,818 0.58
24 /avr_gra/avr_isp.jpg 291,754 0.53
25 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 272,980 0.50
Sum 54,911,375 100.00

To top of page

Top 25 of 3199 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 89,140 9.24
2 /avr_en/index.html 64,806 6.72
3 /avr_de/index.html 64,196 6.66
4 /avr_en/beginner/index.html 28,820 2.99
5 /avr_en/beginner/RIGHT.html 26,266 2.72
6 /avr_en/beginner/LEFT.html 25,624 2.66
7 /avr_de/beginner/index.html 24,722 2.56
8 /avr_de/beginner/rechts.html 24,648 2.56
9 /avr_de/beginner/links.html 23,957 2.48
/avr_en/beginner/HARDWARE.
10 16,737 1.74
html
11 /avr_de/beginner/hardware.html 12,758 1.32
12 /avr_en/AVR_TUT.html 10,466 1.09
13 /avr_de/beginner/werkzeuge.html 9,991 1.04
14 /avr_en/AVR_ADC500.html 9,020 0.94
15 /avr_de/avr_tut.html 9,020 0.94
16 /avr_en/beginner/REGISTER.html 8,807 0.91
17 /avr_en/beginner/TOOLS.html 8,703 0.90
18 /avr_de/beginner/sprung.html 8,639 0.90
19 /avr_de/beginner/register.html 8,138 0.84
20 /avr_de/apps.html 8,115 0.84
21 /akkuload/de/index.html 8,035 0.83
22 /avr_en/beginner/JUMP.html 8,000 0.83
23 /avr_de/lcd4_500.html 7,727 0.80
24 /avr_de/beginner/ports.html 7,688 0.80
25 /avr_de/beginner/rechnen.html 7,442 0.77
Sum 964,205 100.00

To top of page

Top 25 of 3199 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 1,265,527 12.23
2 /avr_en/index.html 1,188,483 11.48
3 /index.html 458,247 4.43
4 /avr_de/beginner/sprung.html 237,852 2.30
5 /avr_de/dcf77uhr.html 231,504 2.24
6 /avr_en/beginner/JUMP.html 185,313 1.79
7 /avr_de/beginner/rechnen.html 184,221 1.78
8 /avr_en/beginner/RIGHT.html 179,785 1.74
9 /avr_de/beginner/rechts.html 166,554 1.61
10 /avr_en/AVR_ADC500.html 140,332 1.36
11 /avr_en/beginner/CALC.html 138,613 1.34
12 /avr_de/beginner/pdetail.html 127,688 1.23
13 /avr_de/beginner/commands.html 122,606 1.18
/avr_en/beginner/HARDWARE.
14 120,231 1.16
html
15 /avr_en/beginner/PDETAIL.html 115,521 1.12
16 /avr_de/keypad/keyboard.html 114,565 1.11
17 /avr_de/beginner/werkzeuge.html 113,267 1.09
18 /avr_en/beginner/LEFT.html 111,768 1.08
19 /avr_de/avr_dac.html 111,227 1.07
20 /avr_de/avr_adc500.html 104,673 1.01
21 /avr_de/beginner/links.html 103,315 1.00
22 /avr_en/beginner/REGISTER.html 101,420 0.98
/avr_en/beginner/COMMANDS.
23 98,471 0.95
html
24 /avr_en/AVR_DAC.html 96,986 0.94
25 /avr_en/keypad/keyboard.html 96,692 0.93
Sum 10,350,669 100.00

To top of page

Top 25 of 337 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 140,309 20.44
2 /avr_gra/stk_lcd.jpg 110,174 16.05
3 /avr_gra/r2r_sine.jpg 78,163 11.39
4 /avr_gra/8515.jpg 27,525 4.01
5 /avr_gra/avr_isp.jpg 26,885 3.92
6 /avr_gra/exp_2313.jpg 26,781 3.90
7 /avr_gra/exp2313g.jpg 26,717 3.89
8 /avr_gra/AT90S8515.jpg 17,915 2.61
9 /avr_gra/pwm_simul.jpg 13,491 1.97
10 /avr_gra/adc8conn.jpg 13,421 1.96
11 /avr_gra/apps.jpg 12,649 1.84
12 /avr_gra/r2r_sawtooth.jpg 12,408 1.81
13 /avr_gra/r2r_wave.jpg 11,988 1.75
14 /avr_gra/r2r_hardware.jpg 11,694 1.70
15 /avr_gra/r2r_sawtooth741.jpg 11,600 1.69
/avr_gra/r2r_sawtoothupperbound.
16 11,500 1.68
jpg
17 /avr_gra/r2r_triangle.jpg 11,482 1.67
18 /avr_gra/r2r_upperbound.jpg 11,447 1.67
19 /akkuload/dscf0030s.jpg 11,422 1.66
20 /avr_gra/stk200.jpg 8,205 1.20
21 /avr_gra/stk200lcd.jpg 8,195 1.19
22 /avr_gra/stk_ram.jpg 8,017 1.17
23 /avr_gra/r2R_sInE.jpg 7,586 1.11
24 /cq-dl/exp2323.jpg 7,028 1.02
/avr_de/praesentation/zuendtester.
25 6,536 0.95
jpg
Sum 686,476 100.00

To top of page

Top 25 of 625 GIF-files , sorted by number of files

N GIF-files times %
/common/knowhow.
1 110,680 5.14
gif
2 /common/akkuload.gif 110,552 5.13
3 /common/app.gif 110,532 5.13
4 /common/r2r.gif 110,375 5.12
5 /common/gavrasm.gif 110,077 5.11
6 /common/example.gif 109,959 5.10
7 /common/clock.gif 109,944 5.10
8 /common/beginner.gif 109,903 5.10
/common/gavrasmw.
9 109,724 5.09
gif
10 /common/calc.gif 109,665 5.09
11 /common/hardware.gif 109,664 5.09
12 /common/adc.gif 109,425 5.08
13 /common/keyb.gif 85,250 3.96
14 /avr_2313.gif 71,321 3.31
15 /dg4fac.gif 71,141 3.30
16 /avr-asm-tutorial.gif 70,923 3.29
17 /avr_gra/2313.gif 46,692 2.17
18 /common/tn13.gif 39,277 1.82
19 /avr_gra/exp2313.gif 27,863 1.29
20 /avr_gra/avr_isp.gif 27,032 1.25
21 /avr_gra/isp10pin.gif 26,833 1.25
22 /avr_gra/isp6pin.gif 26,775 1.24
23 /avr_gra/screenshot.gif 21,481 1.00
24 /gavrasm/gavrasm.gif 13,742 0.64
25 /avr_gra/adc8_hard.gif 13,485 0.63
Sum 2,155,207 100.00

To top of page

Top 25 of 433 entry pages , sorted by number of files

N entry pages times %


1 /index.html 34,838 24.36
2 /avr_de/index.html 12,302 8.60
3 /avr_en/index.html 10,954 7.66
4 /avr_en/beginner/HARDWARE.html 4,764 3.33
5 /avr_de/beginner/index.html 4,519 3.16
6 /avr_en/beginner/index.html 3,427 2.40
7 /avr_de/beginner/hardware.html 2,959 2.07
8 /avr_de/rechnen/konversion.html 2,959 2.07
9 /avr_en/calc/CONVERSION.html 2,864 2.00
10 /avr_de/avr_dac.html 2,653 1.86
11 /avr_de/beginner/werkzeuge.html 2,439 1.71
12 /avr_en/AVR_DAC.html 2,325 1.63
13 /akkuload/de/index.html 1,903 1.33
14 /avr_en/AVR_ADC500.html 1,819 1.27
15 /avr_de/beginner/rechnen.html 1,728 1.21
16 /avr_de/avr_adc500.html 1,726 1.21
17 /avr_de/rechnen/index.html 1,437 1.00
18 /avr_de/beginner/sprung.html 1,414 0.99
19 /gavrasm/index_de.html 1,362 0.95
20 /avr_en/beginner/TOOLS.html 1,269 0.89
21 /avr_de/beginner/pdetail.html 1,188 0.83
22 /avr_de/lcd4_500.html 1,142 0.80
23 /avr_de/rechnen/konvert.html 1,026 0.72
24 /avr_de/keypad/keyboard.html 1,010 0.71
/avr_de/rechteckgen/rectgen_m8.
25 1,003 0.70
html
Sum 142,996 100.00

To top of page

Top 25 of 864 cheat pages , sorted by number of files

N cheat pages times %


1 49,413 21.13
2 /index.html 23,130 9.89
3 /avr_de/index.html 15,316 6.55
4 /avr_en/index.html 14,736 6.30
/avr_en/beginner/HARDWARE.
5 5,881 2.52
html
6 /avr_de/beginner/hardware.html 4,162 1.78
7 /avr_de/beginner/rechts.html 3,515 1.50
8 /avr_de/avr_dac.html 3,298 1.41
9 /avr_en/beginner/RIGHT.html 3,118 1.33
10 /akkuload/de/index.html 3,007 1.29
11 /avr_de/beginner/werkzeuge.html 2,966 1.27
12 /avr_en/AVR_DAC.html 2,952 1.26
13 /avr_en/AVR_ADC500.html 2,719 1.16
14 /avr_de/beginner/rechnen.html 2,559 1.09
15 /avr_de/beginner/sprung.html 2,461 1.05
16 /avr_de/rechnen/konvert.html 2,384 1.02
17 /avr_de/rechnen/konversion.html 2,274 0.97
18 /avr_de/avr_adc500.html 2,183 0.93
19 /avr_de/keypad/keyboard.html 2,135 0.91
20 /avr_en/calc/CONVERT.html 2,055 0.88
21 /avr_en/calc/CONVERSION.html 1,984 0.85
22 /gavrasm/index_de.html 1,914 0.82
23 /avr_en/beginner/TOOLS.html 1,820 0.78
24 /avr_de/lcd4_500.html 1,786 0.76
25 /cq-dl/teil4/index.html 1,763 0.75
Sum 233,805 100.00

To top of page

Top 25 of 373 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 78,011 14.53
2 /avr_en/index.html 62,946 11.72
3 /avr_en/beginner/index.html 47,355 8.82
4 /avr_de/beginner/index.html 43,296 8.06
5 / 37,968 7.07
6 /avr_en/beginner/RIGHT.html 23,858 4.44
7 /avr_de/beginner/links.html 21,672 4.04
8 /avr_de/beginner/rechts.html 21,139 3.94
9 /avr_en/beginner/LEFT.html 19,765 3.68
10 /avr_en/ 14,525 2.71
11 /sitemap_de.html 13,254 2.47
12 /sitemap_en.html 11,482 2.14
13 /avr_de/ 9,895 1.84
14 /avr_en/AVR_TUT.html 8,549 1.59
15 /avr_de/avr_tut.html 7,194 1.34
16 /index.html 7,032 1.31
17 /avr_de/apps.html 5,893 1.10
18 /avr_en/calc/index.html 5,854 1.09
19 /avr_de/rechnen/index.html 5,662 1.05
20 /avr_en/APPS.html 4,752 0.88
21 /weblox_de/index.html 3,804 0.71
22 /weblox_en/index.html 3,651 0.68
/avr_de/beginner/commands.
23 3,332 0.62
html
24 /avr_en/AVR_HARD.html 3,044 0.57
/avr_en/calc/CONVERSION.
25 2,850 0.53
html
Sum 536,956 100.00

To top of page

Top 25 of 5639 external referrers , sorted by number of files

N external referrers times %


1 - 215,252 79.44
2 http://r.webring.com/hub?ring=avr 4,269 1.58
3 http://www.freeweb.hu/vfx/avr/index.html 2,345 0.87
4 http://www.mikrocontroller.net/articles/Linksammlung 1,386 0.51
http://www.elektronik-kompendium.de/public/arnerossius/schalt/mikro/av
5 886 0.33
rkurs.htm
6 http://www.serasidis.gr/links.htm 883 0.33
7 http://www.mikrocontroller.net/articles/AVR 839 0.31
8 http://www.rowalt.de/mc/avr/linksd.htm 797 0.29
9 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 709 0.26
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
10 674 0.25
ESC_by1_bz0_bs0.html
11 http://aquarius.ime.eb.br/~pinho/micro/ 648 0.24
http://www.avrfreaks.net/index.php?
12 name=PNphpBB2&file=viewtopic&t=3698 648 0.24
8
13 http://avr-asm.tripod.com/ 619 0.23
14 http://www.dg4fac.de/rechtsunten.html 600 0.22
15 http://en.wikibooks.org/wiki/Atmel_AVR 584 0.22
16 http://www.dg4fac.de/linksunten.html 584 0.22
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
17 541 0.20
kurs.htm
18 http://miarroba.com/foros/ver.php?foroid=551641&temaid=4566219 495 0.18
19 http://home.wanadoo.nl/electro1/avr/avrlinks.htm 481 0.18
20 http://www.eg3.com/WebID/embedded/avr/blank/tutorial/a-z.htm 467 0.17
21 http://www.eg3.com/WebID/software/assembly/blank/tutorial/a-z.htm 464 0.17
22 http://de.wikipedia.org/wiki/Atmel_AVR 458 0.17
23 http://www.2k-software.de/ingo/programass.html 444 0.16
24 http://de.wikipedia.org/wiki/R2R-Netzwerk 430 0.16
25 http://frank.bol.ucla.edu/avr.htm 426 0.16
Sum 270,978 100.00

To top of page

Top 25 of 578 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 68,680 45.85
2 http://www.google.com 25,186 16.81
3 http://www.google.at 5,217 3.48
4 http://www.google.ch 3,284 2.19
5 http://search.yahoo.com 3,002 2.00
6 http://www.google.co.in 2,890 1.93
7 http://www.google.pl 2,716 1.81
8 http://www.google.ca 2,231 1.49
9 http://www.google.co.uk 2,183 1.46
10 http://www.google.nl 1,990 1.33
11 http://www.google.com.au 1,798 1.20
12 http://www.google.se 1,583 1.06
13 http://www.google.fi 1,217 0.81
14 http://www.google.co.id 1,181 0.79
15 http://www.google.it 1,040 0.69
16 http://www.google.ro 1,024 0.68
17 http://www.google.com.vn 1,009 0.67
18 http://www.google.fr 958 0.64
http://www.google.com.
19 887 0.59
mx
20 http://www.google.be 840 0.56
21 http://www.google.co.kr 831 0.55
http://de.search.yahoo.
22 804 0.54
com
23 http://www.google.com.br 736 0.49
24 http://www.google.gr 664 0.44
25 http://www.google.lt 586 0.39
Sum 149,785 100.00

To top of page

Top 25 of 64498 search strings , sorted by number of files

N search strings times %


1 avr 5,529 3.69
2 avr tutorial 3,750 2.50
3 AVR 1,959 1.31
4 assembler tutorial 1,861 1.24
5 avr assembler 1,854 1.24
6 assembler 1,465 0.98
7 mikrokontroller 712 0.48
8 avr asm 644 0.43
9 stk500 601 0.40
10 AVR tutorial 556 0.37
11 asm tutorial 478 0.32
12 atmel tutorial 471 0.31
13 avr assembly 452 0.30
14 avr asm tutorial 440 0.29
15 Assembler 439 0.29
16 binary division 435 0.29
avr assembler
17 432 0.29
tutorial
18 assembler lernen 395 0.26
19 atmega16 391 0.26
20 avr beginner 380 0.25
21 avr 379 0.25
22 wavrasm 373 0.25
23 gavrasm 363 0.24
24 avr pwm 354 0.24
25 r2r netzwerk 342 0.23
Sum 149,785 100.00

To top of page

Top 10 of 10 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 3,552,501 83.45
2 304 Not changed 548,149 12.88
3 404 File not found 79,375 1.86
4 206 Partial information 46,314 1.09
5 301 Permanently moved 23,256 0.55
6 300 Multiple choices 3,729 0.09
7 xxx Unknown error 2,570 0.06

http://www.avr-asm-tutorial.net/weblox_en/2006y.html (1 of 2)1/20/2009 8:04:48 PM


Weblog statistic for http://www.avr-asm-tutorial.net

8 403 Forbidden 1,071 0.03


9 400 Error in request 38 0.00
10 405 Method not allowed 33 0.00
Sum 4,257,036 100.00

To top of page

Top 25 of 2537 files not found , sorted by number of files

N files not found times %


1 /avr_gra/r2r_sine.jpg 63,347 79.81
2 /beginner_en.pdf 5,773 7.27
3 /beginner_de.pdf 1,511 1.90
4 /_vti_inf.html 440 0.55
5 /avr_de/beginner/planung.html 278 0.35
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
6 %20la 240 0.30
nguage_files/LEFT.htm
7 /gavrasm/v19/instr.asm 234 0.29
/MSOffice/cltreq.asp?
8 215 0.27
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
9 /gavrasm/v17/DosRead.Txt 206 0.26
/MSOffice/cltreq.asp?
10 134 0.17
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
11 120 0.15
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
12 /akkuload/de/accucalc.asm 82 0.10
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
13 20AVR-Assemble 79 0.10
r-Dateien/links.htm
/_vti_bin/owssvr.dll?
14 73 0.09
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
15 /gavrasm/v16/DosRead.Txt 73 0.09
/_vti_bin/owssvr.dll?
16 69 0.09
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
17 66 0.08
UL=1&ACT=4&BUILD=5606&STRMVER=4&CAPREQ=0
18 /gavrasm/v16/instr.asm 66 0.08
19 /gavrasm/v16/gavrasm_sources_doswin.zip 63 0.08
/_vti_bin/owssvr.dll?
20 60 0.08
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
21 /gavrasm/v16/ReadMe.Txt 60 0.08
22 /avr_de/quellen/pcm2pwg4.asm/index.html 59 0.07
23 /gavrasm/v16/gavrasm_sources_lin.zip 59 0.07
24 /gavrasm/v16/gavrasm_lin_en.zip 53 0.07
25 /gavrasm/v18/instr.asm 51 0.06
Sum 79,375 100.00

To top of page

Top 25 of 871 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 2,317,658 54.44
2 Mozilla/5.0 1,616,738 37.98
3 Mozilla/4.5 40,667 0.96
4 Opera/9.00 31,438 0.74
5 Opera/9.02 27,537 0.65
6 Opera/9.01 22,759 0.53
7 - 11,752 0.28
8 msnbot/1.0 11,557 0.27
9 Opera/8.50 9,690 0.23
10 Opera/8.51 7,049 0.17
11 Opera/8.54 6,039 0.14
12 Mozilla/3.01 5,944 0.14
Teleport
13 4,553 0.11
Pro/1.29
14 Microsoft 4,384 0.10
15 Opera/8.52 4,139 0.10
16 WebCopier v4.2 4,067 0.10
17 msnbot/0.9 3,961 0.09
18 Wget/1.9.1 3,955 0.09
19 Mozilla/2.0 3,498 0.08
20 Mozilla/3.0 3,419 0.08
21 Wget/1.10.2 3,392 0.08
22 WebCopier v4.3 3,386 0.08
23 ia_archiver 3,271 0.08
24 DA 7.0 3,240 0.08
25 BackStreet 3,182 0.07
Sum 4,257,036 100.00

To top of page

Top 25 of 1513 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 2,033,350 47.76
2 Firefox/1.5.0.1 176,878 4.15
3 Firefox/1.0.7 163,353 3.84
4 Firefox/1.5.0.7 155,121 3.64
5 Firefox/1.5.0.4 132,612 3.12
6 Firefox/1.5.0.6 116,843 2.74
7 Firefox/2.0 107,543 2.53
8 Firefox/1.5 79,741 1.87
9 Firefox/1.5.0.3 78,992 1.86
10 MSIE 7.0 73,454 1.73
11 Firefox/1.5.0.8 69,283 1.63
12 Slurp 67,724 1.59
13 MSIE 5.0 60,720 1.43
14 Gecko 57,545 1.35
15 Firefox/1.5.0.2 49,830 1.17
16 unknown 48,540 1.14
17 HTTrack 3.0x 39,916 0.94
18 FDM 35,398 0.83
19 Firefox/1.0.6 32,104 0.75
20 Opera/9.00 31,391 0.74
21 MSIE 5.5 29,534 0.69
22 Opera/9.02 27,116 0.64
23 MSIE 5.01 26,606 0.62
24 Firefox/1.5.0.5 23,576 0.55
25 Firefox/1.0 23,478 0.55
Sum 4,257,036 100.00

To top of page

Top 25 of 212 operating systems , sorted by number of files

N operating systems times %


1 Windows NT 5.1 1,880,303 44.17
2 Windows 1,284,305 30.17
3 Windows NT 5.0 290,005 6.81
4 unknown 266,006 6.25
5 Windows 98 199,919 4.70
6 Linux i686 164,649 3.87
7 Macintosh 45,662 1.07
8 Windows NT 4.0 31,933 0.75
9 Linux 22,325 0.52
10 Windows NT 5.2 19,985 0.47
11 Linux x86_64 6,739 0.16
12 Win32 6,518 0.15
13 Linux i686 5,361 0.13
14 Windows 95 4,663 0.11
15 FreeBSD i386 2,628 0.06
16 Windows NT 6.0 2,331 0.05
17 Windows NT 2,181 0.05
18 Windows XP 5.1 1,750 0.04
19 SunOS sun4u 1,679 0.04
20 Windows ME 1,658 0.04
21 Windows NT 5.1. 1,368 0.03
22 Windows XP 1,113 0.03
23 SunOS 5.6 sun4u 1,020 0.02
24 Linux i586 1,019 0.02
25 Windows CE 1,003 0.02
Sum 4,257,036 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 132,762 3.12
2 01 96,546 2.27
3 02 79,135 1.86
4 03 70,578 1.66
5 04 69,612 1.64
6 05 72,565 1.70
7 06 79,423 1.87
8 07 107,618 2.53
9 08 145,518 3.42
10 09 184,947 4.34
11 10 211,514 4.97
12 11 222,700 5.23
13 12 236,407 5.55
14 13 241,889 5.68
15 14 248,997 5.85
16 15 250,333 5.88
17 16 242,831 5.70
18 17 238,356 5.60
19 18 226,646 5.32
20 19 233,826 5.49
21 20 235,643 5.54
22 21 240,399 5.65
23 22 211,920 4.98
24 23 176,871 4.15
Sum 4,257,036 100.00

To top of page

Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2006y.html (2 of 2)1/20/2009 8:04:48 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2005y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2005

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 222764 IPs and host names , sorted by number of files

N IPs and host names times %


1 195.37.237.26=(not found) 9,138 0.25
2 212.185.168.122=(not found) 3,739 0.10
3 65.19.150.237=(not found) 3,034 0.08
4 213.25.33.98=(not found) 2,664 0.07
5 203.160.1.40=localhost 2,648 0.07
6 217.10.50.85=(not found) 2,518 0.07
7 83.16.98.206=adu206.internetdsl.tpnet.pl 2,457 0.07
8 203.162.3.145=proxy01-hcm.vnn.vn 2,402 0.07
9 193.170.68.246=teacheradsl1.eduhi.at 2,217 0.06
10 130.236.49.135=vanheden.isy.liu.se 2,149 0.06
11 203.160.1.70=localhost 2,023 0.06
12 217.194.34.123=arki.erlm.siemens.de 2,018 0.06
66.249.66.242=crawl-66-249-66-242.googlebot.
13 1,909 0.05
com
14 203.162.3.147=proxy03-hcm.vnn.vn 1,775 0.05
15 193.196.64.2=rz02.HS-Karlsruhe.DE 1,758 0.05
16 82.135.143.53=82-135-143-53.ip.takas.lt 1,750 0.05
17 212.63.46.212=clemensburse.hannover.kkf.net 1,744 0.05
18 203.162.3.146=proxy02-hcm.vnn.vn 1,686 0.05
19 83.18.45.182=avt182.internetdsl.tpnet.pl 1,675 0.05
20 168.209.98.35=netcache6.is.co.za 1,670 0.05
21 202.159.27.15=engineer-1.salatiga.indo.net.id 1,659 0.05
62.143.73.221=ip221.73.1311O-CUD12K-02.ish.
22 1,603 0.04
de
23 62.220.119.12=(not found) 1,600 0.04
24 84.32.79.164=(not found) 1,597 0.04
25 137.189.4.1=csc0g03prb.net.cuhk.edu.hk 1,595 0.04
Sum 3,584,636 100.00

To top of page

Top 25 of 222764 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 65.19.150.237=(not found) 244,077 0.32
2 203.160.1.40=localhost 123,253 0.16
3 203.162.3.145=proxy01-hcm.vnn.vn 118,767 0.15
4 195.93.60.79=cache-frr-ac09.proxy.aol.com 116,744 0.15
5 65.19.150.228=(not found) 113,815 0.15
6 203.160.1.70=localhost 94,017 0.12
7 195.93.60.11=cache-frr-aa05.proxy.aol.com 89,420 0.12
8 203.162.3.147=proxy03-hcm.vnn.vn 87,022 0.11
9 168.209.98.35=netcache6.is.co.za 79,166 0.10
10 203.162.3.146=proxy02-hcm.vnn.vn 78,937 0.10
11 65.19.150.234=(not found) 71,199 0.09
12 219.93.174.100=BRF-CE01-G2-0.tm.net.my 68,145 0.09
13 217.10.50.85=(not found) 66,176 0.09
14 58.187.81.16=(not found) 64,211 0.08
66.249.66.242=crawl-66-249-66-242.googlebot.
15 59,504 0.08
com
16 203.162.3.148=proxy04-hcm.vnn.vn 55,523 0.07
17 217.194.34.123=arki.erlm.siemens.de 53,690 0.07
18 194.39.218.10=http-v.fe.bosch.de 52,343 0.07
19 82.182.97.8=1-1-1-8a.msp.mlm.bostream.se 52,008 0.07
20 203.162.3.77=(not found) 49,692 0.06
21 155.232.250.35=ten-cache1-vif-2.tenet.saix.net 49,089 0.06
22 193.196.64.2=rz02.HS-Karlsruhe.DE 48,517 0.06
23 62.214.125.161=i3ED67DA1.versanet.de 47,036 0.06
24 193.197.74.49=dnsfh.fh-heidelberg.de 45,004 0.06
25 193.170.65.247=(not found) 44,943 0.06
Sum 76,835,133 100.00

To top of page

Top 25 of 40383 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


1 64.242.88.50=sv-crawlfw3.looksmart.com 504 0.24
2 65.214.44.150=egspd42205.ask.com 431 0.21
3 195.93.60.11=cache-frr-aa05.proxy.aol.com 413 0.20
4 68.142.251.107=lj2497.inktomisearch.com 405 0.19
5 66.196.90.32=ab1021.inktomisearch.com 398 0.19
195.93.60.112=cache-frr-ad10.proxy.aol.
6 346 0.17
com
7 65.54.188.100=msnbot.msn.com 338 0.16
195.93.60.113=cache-frr-ad11.proxy.aol.
8 337 0.16
com
9 66.194.6.74=66-194-6-74.gen.twtelecom.net 318 0.15
10 64.242.88.10=sv-crawl.looksmart.com 313 0.15
11 66.194.6.84=66-194-6-84.gen.twtelecom.net 312 0.15
12 66.194.6.75=66-194-6-75.gen.twtelecom.net 307 0.15
13 68.142.251.73=lj2463.inktomisearch.com 306 0.15
14 66.194.6.77=66-194-6-77.gen.twtelecom.net 302 0.14
15 65.54.188.101=msnbot.msn.com 296 0.14
16 66.194.6.71=66-194-6-71.gen.twtelecom.net 295 0.14
17 68.142.251.137=lj2527.inktomisearch.com 289 0.14
18 195.93.60.82=cache-frr-ac12.proxy.aol.com 286 0.14
19 68.142.251.86=lj2476.inktomisearch.com 285 0.14
20 66.194.6.80=66-194-6-80.gen.twtelecom.net 283 0.14
21 66.194.6.73=66-194-6-73.gen.twtelecom.net 278 0.13
22 64.241.242.18=sv-fw.looksmart.com 277 0.13
23 66.194.6.72=66-194-6-72.gen.twtelecom.net 277 0.13
24 68.142.251.62=lj2452.inktomisearch.com 276 0.13
25 66.194.6.76=66-194-6-76.gen.twtelecom.net 275 0.13
Sum 209,597 100.00

To top of page

Top 25 of 323 countries of origin , sorted by number of files

N countries of origin times %


1 net 809,177 22.57
2 (unresolved) 740,898 20.67
3 Germany 693,177 19.34
4 com 296,747 8.28
5 Poland 109,333 3.05
6 Austria 100,197 2.80
7 Netherlands 66,695 1.86
8 Switzerland 59,646 1.66
9 Australia 38,282 1.07
10 Sweden 36,856 1.03
11 Italy 36,789 1.03
12 Brazil 31,476 0.88
13 edu 30,013 0.84
14 Belgium 29,692 0.83
15 Mexico 29,107 0.81
16 Finland 28,303 0.79
17 Canada 27,297 0.76
18 Czech Republic 23,090 0.64
19 Greece 22,099 0.62
20 Romania 21,918 0.61
21 Hungary 21,227 0.59
22 United Kingdom 21,224 0.59
23 Lithuania 20,418 0.57
24 France 16,748 0.47
25 Russian Federation 16,703 0.47
Sum 3,584,636 100.00

To top of page

Top 25 of 1209 pathes , sorted by number of files

N pathes times %
1 /common/ 1,161,513 32.40
2 /avr_gra/ 913,280 25.48
3 / 499,263 13.93
4 /avr_en/beginner/ 167,004 4.66
5 /avr_de/beginner/ 148,520 4.14
6 /avr_en/ 147,931 4.13
7 /avr_de/ 139,391 3.89
8 /avr_en/source/ 60,308 1.68
9 /avr_en/calc/ 52,520 1.47
10 /avr_de/quellen/ 46,783 1.31
11 /avr_de/rechnen/ 36,239 1.01
12 /gavrasm/ 32,125 0.90
13 /cq-dl/teil3/ 19,438 0.54
14 /cq-dl/teil1/ 18,527 0.52
15 /cq-dl/teil4/ 17,426 0.49
16 /akkuload/ 16,710 0.47
17 /cq-dl/ 11,660 0.33
18 /akkuload/de/ 10,070 0.28
19 /cq-dl/teil2/ 9,928 0.28
20 /akkuload/en/ 9,597 0.27
21 /weblox_en/ 8,787 0.25
22 /weblox_de/ 8,048 0.22
/akkuload/
23 5,678 0.16
schematic/
24 /gavrasm/v15/ 3,407 0.10
25 /gavrasm/v13/ 3,027 0.08
Sum 3,584,636 100.00

To top of page

Top 25 of 1209 pathes , sorted by kbytes

N pathes kbytes %
1 / 56,441,877 73.46
2 /avr_gra/ 7,143,037 9.30
3 /avr_de/ 1,814,598 2.36
4 /avr_en/ 1,741,691 2.27
5 /avr_de/beginner/ 1,404,234 1.83
6 /avr_en/beginner/ 1,379,482 1.80
7 /weblox_en/ 621,918 0.81
8 /avr_en/calc/ 545,175 0.71
9 /weblox_de/ 541,414 0.70
10 /common/ 458,718 0.60
11 /akkuload/ 413,222 0.54
12 /avr_de/rechnen/ 369,954 0.48
13 /cq-dl/teil4/ 269,874 0.35
14 /avr_en/source/ 268,633 0.35
15 /gavrasm/ 254,184 0.33
/gavrasm/
16 248,535 0.32
gavrasmw/
17 /gavrasm/v15/ 222,805 0.29
18 /avr_de/quellen/ 196,751 0.26
19 /cq-dl/teil1/ 192,507 0.25
20 /gavrasm/v13/ 184,410 0.24
21 /gavrasm/v14/ 163,573 0.21
/akkuload/
22 157,888 0.21
schematic/
23 /avr_de/intro/pdf/ 151,513 0.20
24 /cq-dl/teil3/ 148,897 0.19
25 /gavrasm/v11/ 132,816 0.17
Sum 76,835,133 100.00

To top of page

Top 25 of 4822 requested files , sorted by number of files

N requested files times %


1 /avr_gra/RingLogo.jpg 128,198 3.58
2 /avr_gra/r2r_sine.jpg 100,466 2.80
3 /avr_gra/stk_lcd.jpg 99,485 2.78
4 /common/beginner.gif 99,189 2.77
5 /common/example.gif 99,043 2.76
6 /common/gavrasm.gif 98,945 2.76
/common/gavrasmw.
7 98,891 2.76
gif
/common/knowhow.
8 98,779 2.76
gif
9 /common/calc.gif 98,774 2.76
10 /common/app.gif 98,643 2.75
11 /common/r2r.gif 98,622 2.75
12 /common/hardware.gif 98,614 2.75
13 /common/clock.gif 98,586 2.75
14 /common/adc.gif 98,364 2.74
15 /favicon.ico 82,101 2.29
16 /index.html 78,542 2.19
17 /common/akkuload.gif 75,057 2.09
18 /avr_2313.gif 66,289 1.85
19 /dg4fac.gif 66,077 1.84
20 /avr-asm-tutorial.gif 66,015 1.84
21 /beginner_en.pdf 59,624 1.66
22 /avr_en/index.html 59,306 1.65
23 /avr_de/index.html 55,976 1.56
24 /avr_gra/2313.gif 42,105 1.17
25 /beginner_de.pdf 36,122 1.01
Sum 3,584,636 100.00

To top of page

Top 25 of 4822 requested files , sorted by kbytes

N requested files kbytes %


1 /beginner_en.pdf 23,754,190 30.92
2 /beginner_de.pdf 15,042,183 19.58
3 /avr_en.zip 8,130,562 10.58
4 /avr_de.zip 4,243,492 5.52
5 /Akkulader_Beschreibung.pdf 2,524,035 3.29
6 /avr_2313.gif 1,091,645 1.42
7 /avr_gra/r2r_sine.jpg 1,085,654 1.41
8 /avr_en/index.html 1,000,681 1.30
9 /avr_de/index.html 997,912 1.30
10 /avr_gra/pwm_simul.jpg 712,315 0.93
11 /dg4fac.gif 654,532 0.85
12 /avr_gra/exp2313.gif 441,542 0.57
13 /index.html 391,403 0.51
14 /avr_gra/r2r_hardware.jpg 337,171 0.44
15 /avr_gra/exp2313g.jpg 325,986 0.42
16 /akkuload/dscf0030s.jpg 317,528 0.41
17 /avr_gra/stk_lcd.jpg 307,433 0.40
18 /avr_gra/2313.gif 279,268 0.36
19 /avr_gra/AT90S8515.jpg 263,177 0.34
20 /avr_gra/avr_isp.jpg 262,063 0.34
/gavrasm/gavrasmw/gavrasmW.
21 245,590 0.32
zip
22 /avr_de/dcf77uhr.html 224,058 0.29
23 /avr_de/beginner/sprung.html 197,290 0.26
24 /avr_en/beginner/JUMP.html 187,723 0.24
25 /avr_gra/adc8_int.gif 168,891 0.22
Sum 76,835,133 100.00

To top of page

Top 25 of 3141 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 78,542 9.29
2 /avr_en/index.html 59,306 7.02
3 /avr_de/index.html 55,976 6.62
4 /avr_en/beginner/index.html 25,213 2.98
5 /avr_en/beginner/RIGHT.html 24,644 2.92
6 /avr_en/beginner/LEFT.html 23,982 2.84
7 /avr_de/beginner/rechts.html 21,016 2.49
8 /avr_de/beginner/index.html 20,980 2.48
9 /avr_de/beginner/links.html 20,362 2.41
/avr_en/beginner/HARDWARE.
10 14,699 1.74
html
11 /avr_de/beginner/hardware.html 12,051 1.43
12 /avr_en/AVR_TUT.html 10,452 1.24
13 /avr_en/calc/CONVERSION.html 10,110 1.20
14 /avr_de/avr_tut.html 9,849 1.17
15 /avr_en/beginner/TOOLS.html 9,671 1.14
16 /avr_de/beginner/werkzeuge.html 9,524 1.13
17 /avr_en/beginner/JUMP.html 9,274 1.10
18 /avr_en/beginner/REGISTER.html 8,818 1.04
19 /avr_en/AVR_ADC500.html 8,501 1.01
20 /avr_de/apps.html 8,353 0.99
21 /avr_de/beginner/sprung.html 7,750 0.92
22 /avr_en/beginner/PORTS.html 7,600 0.90
23 /avr_en/beginner/CALC.html 7,336 0.87
24 /avr_de/beginner/register.html 7,319 0.87
25 /avr_de/beginner/ports.html 7,282 0.86
Sum 845,259 100.00

To top of page

Top 25 of 3141 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 1,000,681 11.07
2 /avr_de/index.html 997,912 11.04
3 /index.html 391,403 4.33
4 /avr_de/dcf77uhr.html 224,058 2.48
5 /avr_de/beginner/sprung.html 197,290 2.18
6 /avr_en/beginner/JUMP.html 187,723 2.08
7 /avr_de/beginner/rechnen.html 168,676 1.87
8 /avr_en/beginner/RIGHT.html 164,293 1.82
9 /avr_en/beginner/CALC.html 145,711 1.61
10 /avr_de/beginner/rechts.html 134,153 1.48
11 /avr_en/AVR_ADC500.html 129,547 1.43
12 /avr_de/beginner/commands.html 122,660 1.36
13 /avr_de/beginner/pdetail.html 113,427 1.25
14 /avr_en/beginner/PDETAIL.html 111,243 1.23
15 /avr_de/beginner/werkzeuge.html 106,040 1.17
/avr_en/beginner/COMMANDS.
16 104,697 1.16
html
/avr_en/beginner/HARDWARE.
17 104,044 1.15
html
18 /avr_en/calc/CONVERSION.html 103,841 1.15
19 /avr_de/avr_adc500.html 102,592 1.13
20 /avr_en/calc/CONVERT.html 101,756 1.13
21 /avr_en/beginner/TOOLS.html 101,284 1.12
22 /avr_en/beginner/LEFT.html 96,998 1.07
23 /avr_en/beginner/REGISTER.html 93,407 1.03
24 /cq-dl/teil4/index.html 90,757 1.00
25 /avr_en/AVR_DAC.html 87,657 0.97
Sum 9,040,588 100.00

To top of page

Top 25 of 368 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 128,157 20.79
2 /avr_gra/r2r_sine.jpg 100,400 16.29
3 /avr_gra/stk_lcd.jpg 99,482 16.14
4 /avr_gra/8515.jpg 31,375 5.09
5 /avr_gra/avr_isp.jpg 24,617 3.99
6 /avr_gra/exp_2313.jpg 24,583 3.99
7 /avr_gra/exp2313g.jpg 24,500 3.97
8 /avr_gra/AT90S8515.jpg 18,933 3.07
9 /avr_gra/pwm_simul.jpg 13,477 2.19
10 /avr_gra/adc8conn.jpg 13,462 2.18
11 /avr_gra/apps.jpg 13,026 2.11
12 /avr_gra/r2r_sawtooth.jpg 10,300 1.67
13 /avr_gra/r2r_hardware.jpg 9,871 1.60
/avr_gra/r2r_sawtoothupperbound.
14 9,731 1.58
jpg
15 /avr_gra/r2r_sawtooth741.jpg 9,687 1.57
16 /avr_gra/r2r_triangle.jpg 9,668 1.57
17 /avr_gra/r2r_upperbound.jpg 9,659 1.57
18 /avr_gra/stk200lcd.jpg 9,105 1.48
19 /avr_gra/stk200.jpg 8,755 1.42
20 /akkuload/dscf0030s.jpg 8,329 1.35
21 /avr_gra/stk_ram.jpg 8,020 1.30
22 /cq-dl/exp2323.jpg 7,811 1.27
23 /cq-dl/teil4/stk200.jpg 5,042 0.82
24 /cq-dl/teil3/max232.jpg 4,944 0.80
25 /avr_gra/lcd_conn.jpg 3,713 0.60
Sum 616,413 100.00

To top of page

Top 25 of 615 GIF-files , sorted by number of files

N GIF-files times %
1 /common/beginner.gif 99,187 5.68
2 /common/example.gif 99,040 5.67
3 /common/gavrasm.gif 98,943 5.67
/common/gavrasmw.
4 98,889 5.66
gif
/common/knowhow.
5 98,778 5.66
gif
6 /common/calc.gif 98,773 5.66
7 /common/app.gif 98,643 5.65
8 /common/r2r.gif 98,620 5.65
9 /common/hardware.gif 98,613 5.65
10 /common/clock.gif 98,585 5.64
11 /common/adc.gif 98,358 5.63
12 /common/akkuload.gif 75,052 4.30
13 /avr_2313.gif 66,257 3.79
14 /dg4fac.gif 66,076 3.78
15 /avr-asm-tutorial.gif 66,014 3.78
16 /avr_gra/2313.gif 42,090 2.41
17 /avr_gra/exp2313.gif 26,314 1.51
18 /avr_gra/avr_isp.gif 25,086 1.44
19 /avr_gra/isp10pin.gif 24,660 1.41
20 /avr_gra/isp6pin.gif 24,595 1.41
21 /avr_gra/screenshot.gif 22,572 1.29
22 /avr_gra/adc8.gif 13,515 0.77
23 /avr_gra/adc8_hard.gif 13,491 0.77
24 /avr_gra/adc8_int.gif 13,391 0.77
25 /gavrasm/gavrasm.gif 12,899 0.74
Sum 1,746,506 100.00

To top of page

Top 25 of 340 entry pages , sorted by number of files

N entry pages times %


1 /index.html 30,923 23.55
2 /avr_en/index.html 9,498 7.23
3 /avr_de/index.html 8,549 6.51
4 /avr_en/calc/CONVERSION.html 5,127 3.90
/avr_en/beginner/HARDWARE.
5 4,135 3.15
html
6 /avr_en/beginner/index.html 3,755 2.86
7 /avr_de/beginner/index.html 3,175 2.42
8 /avr_de/beginner/hardware.html 2,954 2.25
9 /avr_de/rechnen/konversion.html 2,621 2.00
10 /avr_de/beginner/werkzeuge.html 2,404 1.83
11 /avr_en/beginner/TOOLS.html 2,111 1.61
12 /avr_en/AVR_ADC500.html 1,914 1.46
13 /avr_de/beginner/rechnen.html 1,900 1.45
14 /avr_en/AVR_DAC.html 1,814 1.38
15 /avr_de/avr_adc500.html 1,758 1.34
16 /avr_de/avr_dac.html 1,428 1.09
17 /avr_en/calc/FPCONV.html 1,354 1.03
18 /avr_en 1,219 0.93
19 /gavrasm/index_de.html 1,170 0.89
20 /avr_de/beginner/pdetail.html 1,111 0.85
21 /avr_en/calc/DIVISION.html 1,044 0.80
22 /avr_de/beginner/sprung.html 1,035 0.79
23 /avr_de/rechnen/konvert.html 1,033 0.79
24 /avr_en/beginner/CALC.html 1,027 0.78
25 /avr_en/beginner/JUMP.html 1,024 0.78
Sum 131,312 100.00

To top of page

Top 25 of 580 cheat pages , sorted by number of files

N cheat pages times %


1 68,592 30.79
2 /index.html 20,270 9.10
3 /avr_en/index.html 12,680 5.69
4 /avr_de/index.html 11,591 5.20
/avr_en/beginner/HARDWARE.
5 4,571 2.05
html
6 /avr_de/beginner/hardware.html 3,658 1.64
7 /avr_en/calc/CONVERSION.html 3,482 1.56
8 /avr_en/calc/CONVERT.html 3,086 1.39
9 /avr_en/beginner/RIGHT.html 2,905 1.30
10 /avr_de/beginner/werkzeuge.html 2,714 1.22
11 /avr_en/AVR_ADC500.html 2,551 1.15
12 /avr_de/beginner/rechnen.html 2,550 1.14
13 /avr_en/beginner/TOOLS.html 2,429 1.09
14 /avr_de/beginner/rechts.html 2,274 1.02
15 /avr_en/AVR_DAC.html 2,268 1.02
16 /avr_de/rechnen/konvert.html 2,199 0.99
17 /avr_de/avr_adc500.html 2,056 0.92
18 /avr_de/avr_dac.html 1,888 0.85
19 /avr_de/rechnen/konversion.html 1,842 0.83
20 /avr_de/beginner/sprung.html 1,781 0.80
21 /cq-dl/teil4/index.html 1,672 0.75
22 /avr_en/beginner/JUMP.html 1,667 0.75
23 /avr_en/beginner/CALC.html 1,558 0.70
24 /gavrasm/index_de.html 1,546 0.69
25 /akkuload/de/index.html 1,540 0.69
Sum 222,764 100.00

To top of page

Top 25 of 382 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 60,768 12.69
2 /avr_en/index.html 40,260 8.41
3 /avr_en/beginner/index.html 39,520 8.25
4 /avr_de/beginner/index.html 34,243 7.15
5 / 32,849 6.86
6 /avr_en/ 30,365 6.34
7 /avr_en/beginner/RIGHT.html 21,891 4.57
8 /avr_en/beginner/LEFT.html 20,694 4.32
9 /avr_de/beginner/links.html 20,601 4.30
10 /avr_de/ 18,704 3.91
11 /avr_de/beginner/rechts.html 18,595 3.88
12 /avr_en/AVR_TUT.html 8,698 1.82
13 /avr_de/avr_tut.html 8,077 1.69
14 /avr_en/calc/index.html 6,069 1.27
15 /avr_en/beginner/ 5,814 1.21
16 /index.html 5,691 1.19
17 /avr_de/rechnen/index.html 4,330 0.90
18 /avr_de/beginner/ 4,261 0.89
/avr_en/calc/CONVERSION.
19 3,921 0.82
html
20 /avr_en/APPS.html 3,750 0.78
21 /avr_de/apps.html 3,607 0.75
22 /weblox_en/index.html 3,314 0.69
/avr_de/beginner/commands.
23 3,308 0.69
html
24 /avr_en/AVR_HARD.html 3,257 0.68
25 /weblox_de/index.html 3,087 0.64
Sum 478,934 100.00

To top of page

Top 25 of 5044 external referrers , sorted by number of files

N external referrers times %


1 - 174,262 79.96
2 http://www.eg3.com/WebID/embedded/avr/blank/tutorial/a-z.htm 2,234 1.03
http://www.elektronik-kompendium.de/public/arnerossius/schalt/mikro/av
3 1,366 0.63
rkurs.htm
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
4 1,239 0.57
ESC_by1_bz0_bs0.html
5 http://www.serasidis.gr/links.htm 1,233 0.57
6 http://www.mikrocontroller.net/articles/Linksammlung 984 0.45
7 http://www.mikrocontroller.net/links.htm 740 0.34
8 http://en.wikibooks.org/wiki/Atmel_AVR 714 0.33
9 http://www.rowalt.de/mc/avr/linksd.htm 693 0.32
10 http://www.2k-software.de/ingo/programass.html 681 0.31
11 http://www.raw-syndicate.us/rubriken/private_elektronik.html 673 0.31
12 http://www.mikrocontroller.net/wiki/AVR 640 0.29
13 http://www.dg4fac.de/rechtsunten.html 639 0.29
14 http://r.webring.com/hub?ring=avr 631 0.29
15 http://www.dg4fac.de/linksunten.html 626 0.29
16 http://home.wanadoo.nl/electro1/avr/avrlinks.htm 527 0.24
17 http://www.lug-kiel.de/links/details/f_avr.html 483 0.22
18 http://www.ime.eb.br/~pinho/micro/ 480 0.22
19 http://www.frogfot.com/links.html 477 0.22
http://www.avrfreaks.net/index.php?
20 module=FreaksAcademy&func=viewItem& 453 0.21
item_id=355&item_type=project
21 http://www.qsl.net/zl1bpu/micro/ENV/ENV.htm 412 0.19
22 378 0.17
http://www.avrfreaks.net/index.php?
23 module=FreaksAcademy&func=viewProje 357 0.16
cts
24 http://www.bol.ucla.edu/~frank/avr.htm 336 0.15
25 http://www.tutorialzone.de/index.php?id=1884 322 0.15
Sum 217,932 100.00

To top of page

Top 25 of 554 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 57,100 39.74
2 http://www.google.com 28,956 20.15
3 http://www.google.at 4,776 3.32
4 http://search.yahoo.com 4,582 3.19
5 http://www.google.ch 3,232 2.25
6 http://www.google.pl 2,814 1.96
7 http://www.google.co.uk 2,692 1.87
8 http://www.google.co.in 2,608 1.82
9 http://www.google.ca 2,496 1.74
10 http://www.google.nl 2,284 1.59
11 http://www.google.com.au 1,832 1.28
12 http://www.google.se 1,734 1.21
13 http://www.google.fi 1,461 1.02
14 http://www.google.it 1,261 0.88
15 http://www.google.be 1,119 0.78
16 http://www.google.fr 1,117 0.78
http://www.google.com.
17 1,030 0.72
mx
18 http://www.google.co.id 935 0.65
19 http://www.google.ro 862 0.60
20 http://www.google.com.br 830 0.58
http://de.search.yahoo.
21 710 0.49
com
22 http://www.google.com.vn 686 0.48
23 http://www.google.lt 660 0.46
24 http://www.google.co.kr 658 0.46
25 http://www.google.dk 602 0.42
Sum 143,685 100.00

To top of page

Top 25 of 65851 search strings , sorted by number of files

N search strings times %


1 avr 4,637 3.23
2 avr tutorial 3,580 2.49
3 assembler tutorial 2,557 1.78
4 AVR 1,629 1.13
5 avr assembler 1,558 1.08
6 assembler 1,409 0.98
7 mikrokontroller 618 0.43
8 asm tutorial 613 0.43
9 binary division 607 0.42
10 stk500 605 0.42
11 AVR tutorial 552 0.38
12 wavrasm 507 0.35
13 avr asm 456 0.32
14 assembler lernen 438 0.30
15 avr pwm 414 0.29
16 atmel tutorial 403 0.28
17 ram testen 367 0.26
avr assembler
18 357 0.25
tutorial
19 Assembler 357 0.25
20 binary calculations 342 0.24
21 avr 338 0.24
22 avr beginner 333 0.23
binary
23 329 0.23
multiplication
24 avr asm tutorial 325 0.23
25 avr board 305 0.21
Sum 143,685 100.00

To top of page

Top 13 of 13 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 2,956,303 82.47
2 304 Not changed 534,410 14.91
3 206 Partial information 73,759 2.06
4 301 Permanently moved 8,773 0.24
5 404 File not found 6,613 0.18

http://www.avr-asm-tutorial.net/weblox_en/2005y.html (1 of 2)1/20/2009 8:05:07 PM


Weblog statistic for http://www.avr-asm-tutorial.net

6 300 Multiple choices 3,453 0.10


7 xxx Unknown error 1,031 0.03
8 403 Forbidden 216 0.01
9 405 Method not allowed 47 0.00
10 400 Error in request 14 0.00
11 xxx Unknown error 12 0.00
12 401 Not authorized 4 0.00
13 501 Not implemented 1 0.00
Sum 3,584,636 100.00

To top of page

Top 25 of 2494 files not found , sorted by number of files

N files not found times %


1 /_vti_inf.html 252 3.81
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
2 20la 180 2.72
nguage_files/LEFT.htm
/_vti_bin/owssvr.dll?
3 119 1.80
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
4 119 1.80
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
5 106 1.60
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 105 1.59
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
7 92 1.39
UL=1&ACT=4&BUILD=5606&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
8 90 1.36
UL=1&ACT=4&BUILD=5606&STRMVER=4&CAPREQ=0
9 /gavrasm/v14/gavrasm_sources_doswin.zip 78 1.18
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
10 20AVR-Assemble 76 1.15
r-Dateien/links.htm
11 /gavrasm/v14/ReadMe.Txt 63 0.95
12 /gavrasm/v14/LiesMich.Txt 54 0.82
13 /avr_de/quellen/mult8.asm/index.html 51 0.77
14 /avr_gra/r2r_sine.jpg 46 0.70
15 /avr_en/beginner/LEFT_data/2313.gif 45 0.68
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
16 20la 41 0.62
nguage_files/RIGHT.htm
/_vti_bin/owssvr.dll?
17 39 0.59
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
18 39 0.59
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
19 38 0.57
UL=1&ACT=4&BUILD=4219&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
20 38 0.57
UL=1&ACT=4&BUILD=4219&STRMVER=4&CAPREQ=0
21 /avr_de/robots.txt 38 0.57
22 /gavrasm/old/v05/LiesMich.Txt 32 0.48
23 /avr_2313.gif 29 0.44
24 /gavrasm/old/v06/LiesMich.Txt 26 0.39
25 /avr_en/source/TEST2.asm/index.html 25 0.38
Sum 6,613 100.00

To top of page

Top 25 of 894 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 2,300,701 64.18
2 Mozilla/5.0 1,066,052 29.74
3 Mozilla/4.5 29,007 0.81
4 Opera/7.54 14,532 0.41
5 Mozilla/3.01 9,459 0.26
6 - 8,868 0.25
7 Opera/8.50 7,202 0.20
8 msnbot/1.0 6,924 0.19
9 Teleport Pro/1.29 6,384 0.18
10 Wget/1.9.1 6,255 0.17
11 Googlebot/2.1 6,211 0.17
12 DA 7.0 5,622 0.16
13 Opera/8.0 5,497 0.15
14 OmniExplorer_Bot/1.09 3,995 0.11
15 Mozilla/3.0 3,516 0.10
16 Opera/8.01 3,470 0.10
17 Opera/7.23 2,590 0.07
18 Xaldon 2,567 0.07
19 Microsoft 2,357 0.07
20 Opera/8.02 2,288 0.06
21 Googlebot-Image/1.0 2,180 0.06
22 WebZIP/6.0 2,014 0.06
23 Mozilla/2.0 1,923 0.05
24 FAST 1,809 0.05
25 Teleport 1,749 0.05
Sum 3,584,636 100.00

To top of page

Top 25 of 1632 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 2,045,254 57.06
2 Firefox/1.0 179,511 5.01
3 Firefox/1.0.7 127,914 3.57
4 Firefox/1.0.4 124,710 3.48
5 Firefox/1.0.6 113,273 3.16
6 MSIE 5.0 79,498 2.22
7 unknown 63,639 1.78
8 MSIE 5.5 59,736 1.67
9 Firefox/1.0.3 51,993 1.45
10 MSIE 5.01 50,901 1.42
11 Firefox/1.0.1 46,126 1.29
12 Firefox/1.0.2 45,062 1.26
13 Gecko 44,394 1.24
14 Firefox/1.5 30,228 0.84
15 HTTrack 3.0x 28,423 0.79
16 Slurp 21,842 0.61
17 FDM 15,729 0.44
18 Firefox/0.10.1 15,236 0.43
19 Opera/7.54 14,532 0.41
Gecko/20030619
20 13,584 0.38
Netscape/7.1
21 Firefox/0.9.3 12,106 0.34
Gecko/20040804
22 11,396 0.32
Netscape/7.2
23 Gecko/20041217 11,158 0.31
24 Gecko/20040910 10,941 0.31
25 Firefox/0.8 10,372 0.29
Sum 3,584,636 100.00

To top of page

Top 25 of 232 operating systems , sorted by number of files

N operating systems times %


1 Windows NT 5.1 1,539,668 42.95
2 Windows 845,584 23.59
3 Windows NT 5.0 413,835 11.54
4 Windows 98 313,596 8.75
5 unknown 194,937 5.44
6 Linux i686 128,601 3.59
7 Windows NT 4.0 40,295 1.12
8 Macintosh 29,896 0.83
9 Linux 22,920 0.64
10 Windows NT 5.2 11,930 0.33
11 Windows 95 6,750 0.19
12 Win32 5,015 0.14
13 Windows NT 4,052 0.11
14 Linux x86_64 3,647 0.10
15 FreeBSD i386 3,153 0.09
16 SunOS sun4u 2,438 0.07
17 Windows ME 2,430 0.07
18 Windows XP 1,841 0.05
19 Linux i586 1,115 0.03
20 Win98 1,113 0.03
21 Win95 898 0.03
22 SunOS 5.6 sun4u 846 0.02
23 Linux ppc 777 0.02
24 Windows CE 660 0.02
25 Windows 2000 560 0.02
Sum 3,584,636 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 110,908 3.09
2 01 84,820 2.37
3 02 69,489 1.94
4 03 61,300 1.71
5 04 59,688 1.67
6 05 62,585 1.75
7 06 67,148 1.87
8 07 83,222 2.32
9 08 120,225 3.35
10 09 155,644 4.34
11 10 174,784 4.88
12 11 188,377 5.26
13 12 200,723 5.60
14 13 206,091 5.75
15 14 210,524 5.87
16 15 214,477 5.98
17 16 209,715 5.85
18 17 203,750 5.68
19 18 194,778 5.43
20 19 189,620 5.29
21 20 188,416 5.26
22 21 186,986 5.22
23 22 183,251 5.11
24 23 158,115 4.41
Sum 3,584,636 100.00

To top of page

Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2005y.html (2 of 2)1/20/2009 8:05:07 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2004y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2004

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 132898 IPs and host names , sorted by number of files

N IPs and host names times %


1 202.249.25.26=(not found) 2,248 0.11
2 66.151.181.4=default-gw.bos3.fastsearch.net 2,093 0.11
3 65.54.164.69=msnbot64069.search.msn.com 1,864 0.10
4 193.170.68.244=fw.eduhi.at 1,847 0.09
5 217.12.63.230=zt.unicom.sk 1,838 0.09
6 217.194.34.123=arki.erlm.siemens.de 1,695 0.09
217.133.221.162=ppp-217-133-221-162.cust-adsl.tiscali.
7 1,661 0.08
it
8 200.136.232.20=(not found) 1,649 0.08
9 202.249.26.62=(not found) 1,423 0.07
10 80.55.237.254=yd254.internetdsl.tpnet.pl 1,404 0.07
11 146.230.128.29=proxy.und.ac.za 1,390 0.07
12 195.227.44.130=(not found) 1,371 0.07
13 130.75.182.66=ip182066.wh.uni-hannover.de 1,362 0.07
14 81.10.8.125=host-81.10.8.125.tedata.net 1,339 0.07
15 200.69.209.253=customer.iplannetworks.net 1,326 0.07
16 203.247.145.53=(not found) 1,267 0.06
17 209.167.50.22=(not found) 1,255 0.06
18 203.162.3.77=(not found) 1,176 0.06
19 213.25.33.98=(not found) 1,149 0.06
20 194.78.68.162=mutoh.be 1,123 0.06
21 192.43.244.42=harvest.ucar.edu 1,119 0.06
22 131.220.96.46=aibn46.astro.uni-bonn.de 1,109 0.06
23 212.113.164.101=a212-113-164-101.netcabo.pt 1,105 0.06
24 212.113.164.100=ce01pc04.netcabo.net 1,060 0.05
25 217.136.224.94=94.224-136-217.adsl-fix.skynet.be 1,027 0.05
Sum 1,958,772 100.00

To top of page

Top 25 of 132898 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 203.162.3.146=(not found) 92,677 0.16
2 203.162.3.148=(not found) 75,780 0.13
217.133.221.162=ppp-217-133-221-162.cust-adsl.tiscali.
3 71,941 0.13
it
4 217.194.34.123=arki.erlm.siemens.de 64,829 0.11
5 130.75.182.66=ip182066.wh.uni-hannover.de 57,839 0.10
6 200.69.209.253=customer.iplannetworks.net 57,349 0.10
7 192.43.244.42=harvest.ucar.edu 57,295 0.10
8 200.136.232.20=(not found) 57,131 0.10
9 81.10.8.125=host-81.10.8.125.tedata.net 51,822 0.09
10 203.247.145.53=(not found) 51,586 0.09
11 149.201.101.250=proxy1.noc.FH-Aachen.DE 50,183 0.09
12 202.249.25.26=(not found) 48,514 0.09
13 195.93.64.7=spider-frr-ta021.proxy.aol.com 47,918 0.08
14 202.249.26.62=(not found) 47,835 0.08
15 203.162.3.147=(not found) 47,370 0.08
16 195.227.44.130=(not found) 47,260 0.08
17 168.209.98.35=netcache6.is.co.za 45,965 0.08
18 212.113.164.101=a212-113-164-101.netcabo.pt 45,161 0.08
19 203.162.3.77=(not found) 44,722 0.08
20 212.113.164.100=ce01pc04.netcabo.net 44,428 0.08
21 193.170.68.244=fw.eduhi.at 44,126 0.08
22 80.55.237.254=yd254.internetdsl.tpnet.pl 43,454 0.08
23 204.29.239.20=sj.us.ircache.net 42,364 0.07
24 80.184.138.153=D8a99.d.pppool.de 41,006 0.07
25 213.139.47.69=(not found) 39,862 0.07
Sum 56,749,473 100.00

To top of page

Top 25 of 23986 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


65.54.164.69=msnbot64069.search.msn.
1 443 0.36
com
66.194.6.73=66-194-6-73.gen.twtelecom.
2 416 0.33
net
66.194.6.80=66-194-6-80.gen.twtelecom.
3 392 0.31
net
4 213.193.30.242=(not found) 358 0.29
66.194.6.83=66-194-6-83.gen.twtelecom.
5 330 0.27
net
6 66.196.65.38=si1004.inktomisearch.com 328 0.26
66.194.6.81=66-194-6-81.gen.twtelecom.
7 322 0.26
net
8 66.196.65.37=si1003.inktomisearch.com 259 0.21
66.194.6.72=66-194-6-72.gen.twtelecom.
9 256 0.21
net
66.194.6.75=66-194-6-75.gen.twtelecom.
10 255 0.20
net
11 213.215.201.235=(not found) 240 0.19
12 217.194.34.123=arki.erlm.siemens.de 233 0.19
195.101.94.209=x1crawler3-1-0.x-echo.
13 228 0.18
com
195.101.94.101=x1crawler2-1-0.x-echo.
14 213 0.17
com
15 216.239.39.5=proxy.google.com 208 0.17
16 64.241.242.18=sv-fw.looksmart.com 205 0.16
17 213.25.33.98=(not found) 200 0.16
18 64.242.88.50=(not found) 200 0.16
66.194.6.84=66-194-6-84.gen.twtelecom.
19 190 0.15
net
20 194.78.68.162=mutoh.be 188 0.15
21 64.68.82.55=crawler11.googlebot.com 184 0.15
22 207.46.98.37=(not found) 182 0.15
23 207.46.98.30=(not found) 175 0.14
24 64.68.82.44=crawler11.googlebot.com 172 0.14
66.194.6.79=66-194-6-79.gen.twtelecom.
25 171 0.14
net
Sum 124,518 100.00

To top of page

Top 25 of 273 countries of origin , sorted by number of files

N countries of origin times %


1 net 512,711 26.18
2 (unresolved) 389,060 19.86
3 Germany 355,030 18.13
4 com 155,045 7.92
5 Austria 58,091 2.97
6 Poland 56,979 2.91
7 Switzerland 35,511 1.81
8 Netherlands 35,109 1.79
9 Australia 22,471 1.15
10 Sweden 19,596 1.00
11 Italy 18,638 0.95
12 Belgium 18,621 0.95
13 Canada 17,331 0.88
14 Finland 16,333 0.83
15 edu 15,034 0.77
16 Brazil 13,953 0.71
17 Mexico 12,733 0.65
18 Greece 12,693 0.65
19 Lithuania 12,342 0.63
20 Portugal 11,298 0.58
21 Romania 10,847 0.55
22 Czech Republic 10,802 0.55
23 Hungary 10,535 0.54
24 Norway 9,334 0.48
25 United Kingdom 9,284 0.47
Sum 1,958,772 100.00

To top of page

Top 25 of 904 pathes , sorted by number of files

N pathes times %
1 /avr_gra/ 606,174 30.95
2 / 402,280 20.54
3 /common/ 211,620 10.80
4 /avr_en/beginner/ 126,024 6.43
5 /avr_en/ 109,708 5.60
6 /avr_de/ 109,413 5.59
7 /avr_de/beginner/ 107,229 5.47
8 /avr_en/calc/ 39,864 2.04
9 /avr_en/source/ 36,481 1.86
10 /gavrasm/ 33,172 1.69
11 /avr_de/rechnen/ 27,587 1.41
12 /avr_de/quellen/ 26,834 1.37
13 /cq-dl/teil3/ 18,216 0.93
14 /cq-dl/teil1/ 17,717 0.90
15 /cq-dl/teil4/ 14,906 0.76
16 /cq-dl/ 11,124 0.57
17 /cq-dl/teil2/ 8,669 0.44
18 /weblox_en/ 6,065 0.31
19 /weblox_de/ 6,046 0.31
20 /gavrasm/v09/ 6,015 0.31
21 /gavrasm/old/v07/ 3,470 0.18
/gavrasm/
22 2,735 0.14
gavrasmw/
23 /gavrasm/v10/ 2,621 0.13
24 /gavrasm/old/v01/ 2,262 0.12
25 /gavrasm/old/v06/ 2,189 0.11
Sum 1,958,772 100.00

To top of page

Top 25 of 904 pathes , sorted by kbytes

N pathes kbytes %
1 / 43,720,411 77.04
2 /avr_gra/ 4,016,700 7.08
3 /avr_de/ 1,228,776 2.17
4 /avr_en/ 1,071,897 1.89
5 /avr_en/beginner/ 1,053,321 1.86
6 /avr_de/beginner/ 995,265 1.75
7 /avr_en/calc/ 405,818 0.72
8 /gavrasm/v09/ 371,575 0.65
9 /weblox_de/ 353,621 0.62
10 /weblox_en/ 342,558 0.60
/gavrasm/
11 317,954 0.56
gavrasmw/
12 /avr_de/rechnen/ 277,567 0.49
13 /gavrasm/ 260,787 0.46
14 /cq-dl/teil4/ 227,645 0.40
15 /gavrasm/old/v07/ 191,739 0.34
16 /avr_en/source/ 186,459 0.33
17 /cq-dl/teil1/ 178,914 0.32
18 /gavrasm/v10/ 168,363 0.30
19 /avr_de/quellen/ 137,232 0.24
20 /cq-dl/teil3/ 134,796 0.24
21 /gavrasm/old/v08/ 119,135 0.21
22 /gavrasm/old/v06/ 113,125 0.20
23 /cq-dl/teil2/ 109,573 0.19
24 /gavrasm/v08/ 107,123 0.19
25 /gavrasm/old/v05/ 104,775 0.18
Sum 56,749,473 100.00

To top of page

Top 25 of 3559 requested files , sorted by number of files

N requested files times %


1 /avr_gra/RingLogo.jpg 109,909 5.61
2 /avr_gra/stk_lcd.jpg 81,541 4.16
3 /index.html 69,628 3.55
4 /avr_2313.gif 60,702 3.10
5 /avr-asm-tutorial.gif 60,391 3.08
6 /dg4fac.gif 57,831 2.95
7 /beginner_en.pdf 51,761 2.64
8 /avr_de/index.html 47,057 2.40
9 /avr_en/index.html 45,604 2.33
10 /beginner_de.pdf 36,531 1.86
11 /favicon.ico 34,541 1.76
12 /avr_gra/2313.gif 29,943 1.53
13 /avr_gra/8515.jpg 24,005 1.23
14 /avr_gra/avr_isp.gif 22,025 1.12
15 /avr_gra/exp2313.gif 21,981 1.12
16 /avr_gra/isp10pin.gif 21,597 1.10
17 /avr_gra/exp2313g.jpg 21,378 1.09
18 /avr_gra/exp_2313.jpg 21,324 1.09
19 /common/beginner.gif 21,319 1.09
20 /avr_gra/isp6pin.gif 21,288 1.09
21 /avr_gra/avr_isp.jpg 21,286 1.09
22 /common/example.gif 21,273 1.09
23 /common/gavrasm.gif 21,243 1.08
/common/gavrasmw.
24 21,177 1.08
gif
25 /common/hardware.gif 21,154 1.08
Sum 1,958,772 100.00

To top of page

Top 25 of 3559 requested files , sorted by kbytes

N requested files kbytes %


1 /beginner_en.pdf 17,845,013 31.45
2 /beginner_de.pdf 13,508,196 23.80
3 /avr_en.zip 6,182,373 10.89
4 /avr_de.zip 3,901,876 6.88
5 /avr_2313.gif 961,971 1.70
6 /avr_de/index.html 629,370 1.11
7 /avr_en/index.html 573,558 1.01
8 /dg4fac.gif 553,535 0.98
9 /avr_gra/pwm_simul.jpg 546,247 0.96
10 /avr_gra/exp2313.gif 355,084 0.63
11 /index.html 340,304 0.60
/gavrasm/gavrasmw/gavrasmW.
12 312,937 0.55
zip
13 /avr_gra/exp2313g.jpg 273,270 0.48
14 /avr_gra/stk_lcd.jpg 238,162 0.42
15 /avr_gra/avr_isp.jpg 219,357 0.39
16 /avr_gra/AT90S8515.jpg 210,260 0.37
17 /avr_de/dcf77uhr.html 193,124 0.34
18 /avr_gra/2313.gif 186,710 0.33
19 /avr_en/beginner/JUMP.html 142,748 0.25
20 /avr_de/beginner/sprung.html 141,672 0.25
21 /avr_gra/adc8_int.gif 129,372 0.23
22 /avr_en/beginner/RIGHT.html 117,225 0.21
23 /avr_de/beginner/rechnen.html 113,901 0.20
24 /avr_en/beginner/CALC.html 112,471 0.20
25 /avr_gra/adc8conn.jpg 111,759 0.20
Sum 56,749,473 100.00

To top of page

Top 25 of 2357 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 69,628 10.80
2 /avr_de/index.html 47,057 7.30
3 /avr_en/index.html 45,604 7.08
4 /avr_en/beginner/index.html 18,410 2.86
5 /avr_en/beginner/RIGHT.html 18,371 2.85
6 /avr_en/beginner/LEFT.html 16,965 2.63
7 /avr_de/beginner/rechts.html 14,436 2.24
8 /avr_de/beginner/index.html 14,211 2.20
9 /avr_de/beginner/links.html 13,770 2.14
/avr_en/beginner/HARDWARE.
10 12,298 1.91
html
11 /avr_de/beginner/hardware.html 10,659 1.65
12 /avr_en/AVR_TUT.html 8,404 1.30
13 /avr_de/avr_tut.html 8,132 1.26
14 /avr_en/beginner/TOOLS.html 7,355 1.14
15 /avr_de/beginner/werkzeuge.html 7,094 1.10
16 /gavrasm/index_de.html 6,676 1.04
17 /avr_en/AVR_ADC500.html 6,539 1.01
18 /avr_en/beginner/JUMP.html 6,459 1.00
19 /avr_en/beginner/REGISTER.html 6,448 1.00
20 /avr_en/calc/CONVERSION.html 6,331 0.98
21 /cq-dl/teil1/index.html 5,739 0.89
22 /avr_de/apps.html 5,615 0.87
23 /avr_de/beginner/sprung.html 5,598 0.87
24 /avr_en/calc/index.html 5,574 0.86
25 /avr_en/beginner/PORTS.html 5,452 0.85
Sum 644,548 100.00

To top of page

Top 25 of 2357 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 629,370 10.11
2 /avr_en/index.html 573,558 9.21
3 /index.html 340,304 5.47
4 /avr_de/dcf77uhr.html 193,124 3.10
5 /avr_en/beginner/JUMP.html 142,748 2.29
6 /avr_de/beginner/sprung.html 141,672 2.28
7 /avr_en/beginner/RIGHT.html 117,225 1.88
8 /avr_de/beginner/rechnen.html 113,901 1.83
9 /avr_en/beginner/CALC.html 112,471 1.81
10 /avr_en/AVR_ADC500.html 99,899 1.60
11 /avr_en/beginner/PDETAIL.html 98,455 1.58
/avr_en/beginner/COMMANDS.
12 91,870 1.48
html
13 /avr_de/beginner/pdetail.html 91,200 1.46
14 /avr_de/beginner/rechts.html 88,278 1.42
/avr_en/beginner/HARDWARE.
15 86,150 1.38
html
16 /avr_de/avr_adc500.html 79,272 1.27
17 /avr_de/beginner/werkzeuge.html 78,058 1.25
18 /avr_de/beginner/commands.html 77,918 1.25
19 /cq-dl/teil4/index.html 75,712 1.22
20 /avr_en/beginner/TOOLS.html 75,303 1.21
21 /avr_de/beginner/hardware.html 72,435 1.16
22 /avr_en/beginner/REGISTER.html 71,760 1.15
23 /avr_en/calc/CONVERT.html 70,063 1.13
24 /avr_en/calc/CONVERSION.html 64,433 1.03
25 /avr_de/beginner/ports.html 59,224 0.95
Sum 6,226,112 100.00

To top of page

Top 25 of 199 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 109,872 29.33
2 /avr_gra/stk_lcd.jpg 81,505 21.76
3 /avr_gra/8515.jpg 23,987 6.40
4 /avr_gra/exp2313g.jpg 21,373 5.71
5 /avr_gra/exp_2313.jpg 21,320 5.69
6 /avr_gra/avr_isp.jpg 21,286 5.68
7 /avr_gra/AT90S8515.jpg 15,669 4.18
8 /avr_gra/pwm_simul.jpg 10,510 2.81
9 /avr_gra/adc8conn.jpg 10,501 2.80
10 /avr_gra/apps.jpg 8,837 2.36
11 /avr_gra/stk200lcd.jpg 8,048 2.15
12 /cq-dl/exp2323.jpg 7,390 1.97
13 /avr_gra/stk200.jpg 6,470 1.73
14 /avr_gra/stk_ram.jpg 5,135 1.37
15 /cq-dl/teil3/max232.jpg 4,562 1.22
16 /cq-dl/teil4/stk200.jpg 4,295 1.15
17 /avr_gra/lcd_conn.jpg 3,143 0.84
18 /avr_gra/lcd_board.jpg 3,140 0.84
19 /avr_gra/remote.jpg 2,723 0.73
20 /avr_gra/sio_conn.jpg 2,255 0.60
21 /avr_gra/pwg.jpg 1,916 0.51
22 /spicons/gforbidden.jpg 185 0.05
23 /spicons/notfound.jpg 173 0.05
24 //avr_gra/RingLogo.jpg 7 0.00
/avr_de/../avr_gra/RingLogo.
25 5 0.00
jpg
Sum 374,573 100.00

To top of page

Top 25 of 386 GIF-files , sorted by number of files

N GIF-files times %
1 /avr_2313.gif 60,696 8.92
2 /avr-asm-tutorial.gif 60,390 8.87
3 /dg4fac.gif 57,829 8.50
4 /avr_gra/2313.gif 29,922 4.40
5 /avr_gra/avr_isp.gif 22,025 3.24
6 /avr_gra/exp2313.gif 21,978 3.23
7 /avr_gra/isp10pin.gif 21,597 3.17
8 /common/beginner.gif 21,319 3.13
9 /avr_gra/isp6pin.gif 21,288 3.13
10 /common/example.gif 21,273 3.13
11 /common/gavrasm.gif 21,243 3.12
/common/gavrasmw.
12 21,177 3.11
gif
13 /common/hardware.gif 21,153 3.11
14 /common/calc.gif 21,152 3.11
15 /common/clock.gif 21,112 3.10
/common/knowhow.
16 21,087 3.10
gif
17 /common/adc.gif 21,047 3.09
18 /common/app.gif 21,046 3.09
19 /avr_gra/screenshot.gif 18,609 2.73
20 /gavrasm/gavrasm.gif 14,046 2.06
21 /avr_gra/adc8.gif 10,571 1.55
22 /avr_gra/adc8_hard.gif 10,524 1.55
23 /avr_gra/adc8_int.gif 10,397 1.53
24 /avr_gra/lcd4conn.gif 9,167 1.35
25 /avr_gra/sram.gif 6,552 0.96
Sum 680,671 100.00

To top of page

Top 25 of 289 entry pages , sorted by number of files

N entry pages times %


1 /index.html 28,392 25.85
2 /avr_de/index.html 9,685 8.82
3 /avr_en/index.html 8,867 8.07
4 /avr_en/beginner/HARDWARE.html 3,353 3.05
5 /avr_de/beginner/hardware.html 3,194 2.91
6 /avr_en/calc/CONVERSION.html 2,656 2.42
7 /avr_en/beginner/index.html 2,413 2.20
8 /avr_de/beginner/index.html 2,412 2.20
9 /avr_de/beginner/werkzeuge.html 1,855 1.69
10 /avr_en/AVR_ADC500.html 1,678 1.53
11 /avr_en/beginner/TOOLS.html 1,639 1.49
12 /avr_de/rechnen/konversion.html 1,525 1.39
13 /avr_de/avr_adc500.html 1,296 1.18
14 /avr_en/calc/FPCONV.html 1,204 1.10
15 /avr_de/beginner/rechnen.html 1,192 1.09
16 /gavrasm/index_de.html 1,052 0.96
17 /avr_en/calc/DIVISION.html 1,024 0.93
18 /avr_en 1,011 0.92
19 /avr_de/beginner/pdetail.html 971 0.88
20 /avr_de/rechnen/index.html 941 0.86
21 /avr_en/calc/index.html 883 0.80
/avr_en/calc/MULTIPLICATION.
22 881 0.80
html
23 /avr_de/testram.html 868 0.79
24 /avr_en/TESTLCD.html 859 0.78
25 /avr_en/calc/CONVERT.html 845 0.77
Sum 109,832 100.00

To top of page

Top 25 of 449 cheat pages , sorted by number of files

N cheat pages times %


1 /index.html 18,594 13.99
2 12,422 9.35
3 /avr_de/index.html 10,129 7.62
4 /avr_en/index.html 9,946 7.48
/avr_en/beginner/HARDWARE.
5 3,744 2.82
html
6 /avr_de/beginner/hardware.html 3,605 2.71
7 /avr_de/beginner/werkzeuge.html 2,212 1.66
8 /avr_en/calc/CONVERT.html 2,099 1.58
9 /avr_en/beginner/RIGHT.html 2,064 1.55
10 /avr_en/AVR_ADC500.html 1,995 1.50
11 /avr_en/beginner/TOOLS.html 1,954 1.47
12 /avr_en/calc/CONVERSION.html 1,939 1.46
13 /avr_de/beginner/rechts.html 1,659 1.25
14 /avr_de/beginner/rechnen.html 1,620 1.22
15 /avr_de/rechnen/konvert.html 1,525 1.15
16 /avr_de/avr_adc500.html 1,515 1.14
17 /gavrasm/index_de.html 1,496 1.13
18 /cq-dl/teil4/index.html 1,352 1.02
19 /avr_en/beginner/JUMP.html 1,256 0.95
20 /avr_de/beginner/sprung.html 1,253 0.94
21 /avr_en/calc/FPCONV.html 1,198 0.90
22 /avr_de/rechnen/konversion.html 1,162 0.87
23 /avr_de/beginner/pdetail.html 1,152 0.87
24 /cq-dl/teil1/index.html 1,150 0.87
25 /avr_en/beginner/CALC.html 1,136 0.85
Sum 132,898 100.00

To top of page

Top 25 of 344 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 47,159 13.39
2 /avr_en/index.html 29,789 8.46
3 / 29,080 8.26
4 /avr_en/beginner/index.html 27,203 7.72
5 /avr_de/beginner/index.html 22,002 6.25
6 /avr_en/ 19,386 5.50
7 /avr_en/beginner/RIGHT.html 16,418 4.66
8 /avr_en/beginner/LEFT.html 15,420 4.38
9 /avr_de/beginner/links.html 14,351 4.08
10 /avr_de/ 12,761 3.62
11 /avr_de/beginner/rechts.html 11,183 3.18
12 /avr_en/AVR_TUT.html 6,721 1.91
13 /avr_de/avr_tut.html 6,064 1.72
14 /index.html 4,760 1.35
15 /avr_en/beginner/ 4,478 1.27
16 /weblox_en/index.html 3,895 1.11
17 /avr_en/calc/index.html 3,697 1.05
18 /avr_de/beginner/ 3,291 0.93
19 /weblox_de/index.html 3,290 0.93
20 /avr_de/rechnen/index.html 3,288 0.93
21 /avr_de/apps.html 2,675 0.76
22 /avr_en/calc/CONVERSION.html 2,534 0.72
23 /avr_en/APPS.html 2,353 0.67
/avr_en/beginner/COMMANDS.
24 2,292 0.65
html
25 /avr_de/beginner/commands.html 2,201 0.63
Sum 352,155 100.00

To top of page

Top 25 of 3679 external referrers , sorted by number of files

N external referrers times %


1 - 142,310 80.63
2 http://www.mikrocontroller.net/links.htm 2,559 1.45
http://forum.electronicwerkstatt.de/phpBB/
3 topic7388_f28_bxtopic_timexD 1,033 0.59
ESC_by1_bz0_bs0.html
4 883 0.50
5 http://www.raw-syndicate.us/rubriken/private_elektronik.html 881 0.50
6 http://www.eg3.com/WebID/embedded/avr/blank/tutorial/a-z.htm 873 0.49
7 http://r.webring.com/hub?ring=avr 732 0.41
8 http://www.rowalt.de/mc/avr/linksd.htm 636 0.36
9 http://www.dg4fac.de/rechtsunten.html 630 0.36
10 http://www.dg4fac.de/linksunten.html 609 0.35
11 http://www.bol.ucla.edu/~frank/avr.htm 563 0.32
12 http://www.qsl.net/zl1bpu/micro/ENV/ENV.htm 524 0.30
13 http://home.wanadoo.nl/electro1/avr/avrlinks.htm 481 0.27
14 http://www.atmel.com/dyn/products/app_notes.asp?family_id=616 467 0.26
15 http://www.ime.eb.br/~pinho/micro/ 458 0.26
http://www.elektronik-kompendium.de/public/arnerossius/schalt/mikro/av
16 445 0.25
rkurs.htm
17 http://www.lug-kiel.de/links/details/f_avr.html 425 0.24
18 http://www.mikrocontroller.net/tutorial/equipment.htm 381 0.22
19 http://s-huehn.de/elektronik/links.htm 316 0.18
20 http://home.pages.at/arnerossius/schalt/mikro/avrkurs.htm 311 0.18
21 http://www.iptel-now.de/HOWTO/ATMEL/atmel.html 267 0.15
22 http://www.lug-kiel.de/links/micros.html 256 0.15
23 http://www.elektronika.qs.pl/asm_avr_jezyk.html 200 0.11
24 http://www.xs4all.nl/~sbp/links/electronics.htm 192 0.11
25 http://www.rowalt.de/mc/avr/about.htm 192 0.11
Sum 176,488 100.00

To top of page

Top 25 of 523 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 42,190 36.95
2 http://www.google.com 26,944 23.60
3 http://search.yahoo.com 5,204 4.56
4 http://www.google.at 3,404 2.98
5 http://www.google.ch 2,484 2.18
6 http://www.google.ca 2,439 2.14
7 http://www.google.pl 2,007 1.76
8 http://www.google.nl 1,856 1.63
9 http://www.google.co.in 1,616 1.42
10 http://www.google.com.au 1,537 1.35
11 http://www.google.se 1,440 1.26
12 http://www.google.fi 1,154 1.01
13 http://www.google.co.uk 1,107 0.97
14 http://www.google.it 1,000 0.88
15 http://www.google.be 913 0.80
16 http://www.google.fr 907 0.79
http://www.google.com.
17 808 0.71
mx
18 http://www.altavista.com 768 0.67
http://de.search.yahoo.
19 701 0.61
com
20 http://www.google.es 580 0.51
21 http://www.google.dk 573 0.50
22 http://www.google.com.br 570 0.50
23 http://www.google.ro 569 0.50
24 http://www.google.lt 542 0.47
25 http://www.google.co.kr 512 0.45
Sum 114,180 100.00

To top of page

Top 25 of 51569 search strings , sorted by number of files

N search strings times %


1 avr 4,024 3.52
2 assembler tutorial 3,059 2.68
3 avr tutorial 2,579 2.26
4 AVR 1,670 1.46
5 avr assembler 1,179 1.03
6 assembler 772 0.68
7 binary division 612 0.54
8 asm tutorial 582 0.51
9 wavrasm 503 0.44
10 binary multiplication 500 0.44
11 stk500 497 0.44
12 ram testen 424 0.37
assembler
13 380 0.33
programmierung
14 avr asm 350 0.31
15 AVR tutorial 347 0.30
16 assembler lernen 346 0.30
17 atmel tutorial 345 0.30
18 avr assembler tutorial 311 0.27
19 mikrokontroller 297 0.26
20 avr pwm 296 0.26
21 Assembler Tutorial 287 0.25
22 binary calculations 279 0.24
23 avr programming 278 0.24
24 Assembler 277 0.24
25 avr board 269 0.24
Sum 114,180 100.00

To top of page

Top 12 of 12 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 1,587,593 81.05
2 304 Not changed 287,103 14.66
3 206 Partial information 66,942 3.42
4 301 Permanently moved 6,931 0.35

http://www.avr-asm-tutorial.net/weblox_en/2004y.html (1 of 2)1/20/2009 8:05:25 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 404 File not found 6,192 0.32


6 300 Multiple choices 2,039 0.10
7 500 Internal error 721 0.04
8 403 Forbidden 597 0.03
9 xxx Unknown error 442 0.02
10 xxx Unknown error 151 0.01
11 405 Method not allowed 60 0.00
12 401 Not authorized 1 0.00
Sum 1,958,772 100.00

To top of page

Top 25 of 1802 files not found , sorted by number of files

N files not found times %


/MSOffice/cltreq.asp?
1 398 6.43
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
2 /_vti_inf.html 230 3.71
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
3 20la 155 2.50
nguage_files/LEFT.htm
/MSOffice/cltreq.asp?
4 137 2.21
UL=1&ACT=4&BUILD=4219&STRMVER=4&CAPREQ=0
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
5 20AVR-Assemble 98 1.58
r-Dateien/links.htm
6 /avr_de/quellen/test1.asm/index.html 86 1.39
/_vti_bin/owssvr.dll?
7 74 1.20
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
8 61 0.99
UL=1&ACT=4&BUILD=5606&STRMVER=4&CAPREQ=0
9 /avr_de/beginner/links_data/2313.gif 59 0.95
10 /index.html 55 0.89
/_vti_bin/owssvr.dll?
11 41 0.66
UL=1&ACT=4&BUILD=4219&STRMVER=4&CAPREQ=0
12 /avr_en/beginner/LEFT_data/2313.gif 34 0.55
13 /avr_de/cq-dl/teil3/index.html 32 0.52
14 /calc/index.html 30 0.48
15 /adc8.html 29 0.47
16 /avr_tut.html 28 0.45
17 /rechnen/index.html 28 0.45
18 /2001y.html 28 0.45
19 /avr_allg.html 27 0.44
20 /avr_soft.html 26 0.42
21 /2004w06.html 25 0.40
22 /avr_de/quellen/div8d.asm/index.html 25 0.40
23 /beginner/index.html 24 0.39
24 /avr_hard.html 24 0.39
25 /avr_adc500.html 24 0.39
Sum 6,192 100.00

To top of page

Top 25 of 695 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 1,464,620 74.77
2 Mozilla/5.0 326,819 16.68
3 Mozilla/4.5 16,793 0.86
4 Mozilla/3.01 8,375 0.43
5 Opera/7.23 7,518 0.38
6 Teleport Pro/1.29 6,687 0.34
7 Googlebot/2.1 6,532 0.33
8 - 6,353 0.32
9 msnbot/0.11 5,340 0.27
10 Xaldon 5,153 0.26
11 WebCopier v4.0 4,260 0.22
12 Opera/7.54 4,079 0.21
13 Wget/1.9.1 3,784 0.19
14 Wget/1.8.2 3,308 0.17
15 WebReaper 3,180 0.16
16 Teleport 3,045 0.16
17 contype 2,756 0.14
18 Mozilla/3.0 2,627 0.13
19 Scooter/3.3_SF 2,239 0.11
20 DA 5.3 2,195 0.11
FAST-WebCrawler/3.8/
21 2,093 0.11
Scirus
22 DA 7.0 2,077 0.11
23 Mozilla/4.7 2,022 0.10
24 msnbot/0.3 1,802 0.09
25 NaverBot-1.0 1,732 0.09
Sum 1,958,772 100.00

To top of page

Top 25 of 1505 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 1,220,596 62.31
2 MSIE 5.5 79,849 4.08
3 MSIE 5.01 66,060 3.37
4 MSIE 5.0 65,561 3.35
5 Firefox/0.8 40,645 2.08
6 Firefox/1.0 35,259 1.80
7 unknown 34,020 1.74
8 Firefox/0.9.3 22,238 1.14
9 Gecko/20040113 19,644 1.00
10 Firefox/0.10.1 17,948 0.92
11 HTTrack 3.0x 14,323 0.73
12 Gecko 13,483 0.69
Gecko/20030624
13 12,291 0.63
Netscape/7.1
Gecko/20030619
14 11,749 0.60
Netscape/7.1
15 MSIE 5.00 9,651 0.49
16 Gecko/20031007 Firebird/0.7 8,745 0.45
17 Konqueror/3.1 8,546 0.44
18 Gecko/20031007 8,530 0.44
19 Opera/7.23 7,518 0.38
20 Firefox/0.9.2 7,271 0.37
21 Pro/1.29 6,687 0.34
22 Googlebot/2.1 6,526 0.33
23 Slurp 6,076 0.31
24 Firefox/0.10 5,936 0.30
25 Gecko/20040910 5,406 0.28
Sum 1,958,772 100.00

To top of page

Top 25 of 268 operating systems , sorted by number of files

N operating systems times %


1 Windows NT 5.1 782,253 39.94
2 Windows NT 5.0 358,856 18.32
3 Windows 98 280,031 14.30
4 Windows 230,068 11.75
5 unknown 140,319 7.16
6 Linux i686 60,206 3.07
7 Windows NT 4.0 31,792 1.62
8 Linux 16,205 0.83
9 Windows 95 7,784 0.40
10 Macintosh 7,206 0.37
11 Windows NT 5.2 6,921 0.35
12 Windows NT 6,553 0.33
13 Win32 5,441 0.28
14 Win98 3,110 0.16
15 Windows XP 1,909 0.10
16 Windows 2000 1,683 0.09
17 SunOS sun4u 1,651 0.08
18 Windows ME 1,585 0.08
19 Linux i586 1,481 0.08
20 WinNT 1,411 0.07
21 FreeBSD 1,126 0.06
22 Win95 1,005 0.05
23 FreeBSD i386 941 0.05
Windows 95/98/2000/
24 597 0.03
NT
25 Linux 2.4.18-4GB i586 523 0.03
Sum 1,958,772 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 62,045 3.17
2 01 46,477 2.37
3 02 37,936 1.94
4 03 33,785 1.72
5 04 30,362 1.55
6 05 31,284 1.60
7 06 32,809 1.67
8 07 47,423 2.42
9 08 66,452 3.39
10 09 79,525 4.06
11 10 91,518 4.67
12 11 108,828 5.56
13 12 114,145 5.83
14 13 119,828 6.12
15 14 116,723 5.96
16 15 118,726 6.06
17 16 116,305 5.94
18 17 106,558 5.44
19 18 105,209 5.37
20 19 102,340 5.22
21 20 104,464 5.33
22 21 106,791 5.45
23 22 97,343 4.97
24 23 81,896 4.18
Sum 1,958,772 100.00

To top of page

Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2004y.html (2 of 2)1/20/2009 8:05:25 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2003y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2003

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 99073 IPs and host names , sorted by number of files

N IPs and host names times %


1 217.255.25.158=pD9FF199E.dip.t-dialin.net 31,014 2.00
2 80.137.245.60=p5089F53C.dip.t-dialin.net 13,748 0.89
3 80.137.244.186=p5089F4BA.dip.t-dialin.net 12,530 0.81
4 212.45.8.219=(not found) 6,859 0.44
5 81.91.37.210=old.shampan.ru 4,306 0.28
6 212.113.164.101=a212-113-164-101.netcabo.pt 4,282 0.28
7 194.65.14.77=pr7-ts.telepac.pt 4,026 0.26
8 209.152.48.180=(not found) 3,109 0.20
80.140.206.153=p508CCE99.dip0.t-ipconnect.
9 2,048 0.13
de
10 216.39.48.20=trek13.sv.av.com 1,965 0.13
11 80.137.223.53=p5089DF35.dip.t-dialin.net 1,730 0.11
12 202.249.25.26=sfc-cache.ai3.net 1,729 0.11
13 216.39.48.87=buildrack44.sv.av.com 1,711 0.11
14 216.39.50.144=drone4.sv.av.com 1,688 0.11
15 196.2.56.5=proxy.cpt.mweb.co.za 1,490 0.10
16 149.203.55.1=(not found) 1,468 0.09
17 137.226.32.170=ac3a20.physik.rwth-aachen.de 1,382 0.09
18 213.134.236.229=(not found) 1,357 0.09
19 216.39.50.158=drone9.sv.av.com 1,318 0.09
20 213.193.30.242=(not found) 1,178 0.08
21 194.138.37.36=proxy1-uunet.sbs.de 1,163 0.08
22 66.77.73.170=cr011r01-3.sac2.fastsearch.net 1,147 0.07
23 212.105.36.21=md4692415.utfors.se 1,146 0.07
24 203.94.244.130=(not found) 1,143 0.07
25 80.132.135.94=p5084875E.dip0.t-ipconnect.de 1,143 0.07
Sum 1,547,301 100.00

To top of page

Top 25 of 99073 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 212.45.8.219=(not found) 143,048 0.57
2 194.65.14.77=pr7-ts.telepac.pt 138,422 0.55
3 212.113.164.101=a212-113-164-101.netcabo.pt 112,268 0.45
4 80.140.206.153=p508CCE99.dip0.t-ipconnect.de 106,175 0.42
5 213.69.97.199=(not found) 104,916 0.42
6 80.146.81.49=p50925131.dip0.t-ipconnect.de 46,011 0.18
7 202.249.25.26=sfc-cache.ai3.net 44,929 0.18
8 62.167.37.242=adsl-62-167-37-242.adslplus.ch 43,543 0.17
9 213.134.236.229=(not found) 43,019 0.17
10 209.152.48.180=(not found) 40,586 0.16
11 195.233.250.7=(not found) 40,365 0.16
12 80.140.194.115=p508CC273.dip0.t-ipconnect.de 39,334 0.16
13 80.132.135.94=p5084875E.dip0.t-ipconnect.de 37,972 0.15
14 196.2.56.5=proxy.cpt.mweb.co.za 37,755 0.15
15 194.105.102.99=cpe99.bb102.cablesurf.de 36,456 0.15
16 80.137.245.60=p5089F53C.dip.t-dialin.net 35,516 0.14
17 194.65.100.8=pbr2.telepac.pt 34,153 0.14
217.230.235.102=pD9E6EB66.dip0.t-ipconnect.
18 33,726 0.13
de
19 149.203.55.1=(not found) 33,301 0.13
20 217.255.25.158=pD9FF199E.dip.t-dialin.net 33,209 0.13
21 195.233.250.6=(not found) 32,959 0.13
22 203.94.244.130=(not found) 32,611 0.13
23 194.204.62.125=adsl125.uninet.ee 31,813 0.13
24 194.204.173.67=zt.elblag.tpsa.pl 31,530 0.13
25 192.100.124.218=esprx01x.nokia.com 31,257 0.12
Sum 25,108,490 100.00

To top of page

Top 25 of 18250 IPs and host names of multiple visitors , sorted by


number of visits

N IPs and host names of multiple visitors visits %


1 213.193.30.242=(not found) 1,008 0.99
2 66.196.65.38=si1004.inktomisearch.com 872 0.85
3 66.196.65.37=si1003.inktomisearch.com 579 0.57
4 216.39.48.20=trek13.sv.av.com 496 0.48
5 216.39.50.158=drone9.sv.av.com 487 0.48
6 216.39.48.87=buildrack44.sv.av.com 474 0.46
7 216.39.50.145=drone5.sv.av.com 445 0.44
8 216.39.50.144=drone4.sv.av.com 429 0.42
9 193.7.255.242=(not found) 401 0.39
10 216.39.50.143=drone3.sv.av.com 390 0.38
11 66.196.65.25=si3008.inktomisearch.com 348 0.34
12 194.65.14.77=pr7-ts.telepac.pt 335 0.33
13 64.241.242.18=sv-fw.looksmart.com 318 0.31
14 216.39.50.160=drone11.sv.av.com 304 0.30
15 209.73.164.50=bigip1a-snat.sv.av.com 304 0.30
16 66.196.90.249=lj1238.inktomisearch.com 246 0.24
17 216.39.50.116=drone2.sv.av.com 224 0.22
212.113.164.101=a212-113-164-101.netcabo.
18 217 0.21
pt
19 216.39.50.156=drone7.sv.av.com 214 0.21
20 216.39.50.155=drone6.sv.av.com 205 0.20
21 64.156.198.76=unknown.Level3.net 204 0.20
22 216.88.158.142=crawlers.looksmart.com 197 0.19
23 216.239.39.5=(not found) 190 0.19
24 195.93.65.8=cache-frr-ae05.proxy.aol.com 190 0.19
25 195.93.65.13=cache-frr-ae10.proxy.aol.com 186 0.18
Sum 102,285 100.00

To top of page

Top 25 of 207 countries of origin , sorted by number of files

N countries of origin times %


1 net 511,667 33.07
2 (unresolved) 270,103 17.46
3 Germany 223,325 14.43
4 com 136,207 8.80
5 Austria 44,290 2.86
6 Poland 33,053 2.14
7 Netherlands 25,941 1.68
8 Switzerland 21,409 1.38
9 Sweden 18,950 1.22
10 Canada 18,864 1.22
11 Australia 18,793 1.21
12 Portugal 13,916 0.90
13 Belgium 13,566 0.88
14 Norway 13,032 0.84
15 France 12,139 0.78
16 Italy 10,996 0.71
17 edu 10,959 0.71
18 Greece 10,747 0.69
19 Russian Federation 10,320 0.67
20 Finland 9,942 0.64
21 Brazil 9,477 0.61
22 Romania 8,128 0.53
23 United Kingdom 8,089 0.52
24 Denmark 7,786 0.50
25 Czech Republic 7,540 0.49
Sum 1,547,301 100.00

To top of page

Top 25 of 1199 pathes , sorted by number of files

N pathes times %
1 /avr_gra/ 554,588 35.84
2 / 206,924 13.37
/avr_en/
3 138,711 8.96
beginner/
/avr_de/
4 119,165 7.70
beginner/
5 /avr_de/ 101,025 6.53
6 /avr_en/ 97,841 6.32
7 /avr_en/calc/ 36,889 2.38
8 /gavrasm/ 35,284 2.28
9 /avr_en/source/ 31,852 2.06
10 /avr_de/rechnen/ 27,322 1.77
11 /gavrasm/v06/ 25,845 1.67
12 /avr_de/quellen/ 24,638 1.59
13 /cq-dl/teil3/ 17,281 1.12
14 /cq-dl/teil1/ 16,836 1.09
15 /cq-dl/teil4/ 16,069 1.04
16 /gavrasm/v01/ 12,404 0.80
17 /cq-dl/ 11,511 0.74
18 /weblox_de/ 10,622 0.69
19 /weblox_en/ 10,459 0.68
20 /gavrasm/v03/ 9,680 0.63
21 /cq-dl/teil2/ 9,150 0.59
22 /gavrasm/v05/ 8,940 0.58
23 /gavrasm/v04/ 7,104 0.46
24 /gavrasm/v02/ 4,054 0.26
25 /spicons/ 1,992 0.13
Sum 1,547,301 100.00

To top of page

Top 25 of 1199 pathes , sorted by kbytes

N pathes kbytes %
1 / 13,508,954 53.80
2 /avr_gra/ 3,456,135 13.76
3 /avr_en/beginner/ 1,123,729 4.48
4 /avr_de/beginner/ 1,015,697 4.05
5 /avr_de/ 922,524 3.67
6 /avr_en/ 809,166 3.22
7 /weblox_en/ 649,453 2.59
8 /weblox_de/ 645,930 2.57
9 /gavrasm/ 449,013 1.79
10 /avr_en/calc/ 392,577 1.56
11 /avr_de/rechnen/ 282,888 1.13
12 /cq-dl/teil4/ 244,853 0.98
13 /cq-dl/teil1/ 165,638 0.66
14 /avr_en/source/ 155,046 0.62
15 /gavrasm/v05/ 137,023 0.55
/gavrasm/
16 134,281 0.53
gavrasmw/
17 /cq-dl/teil3/ 126,587 0.50
18 /avr_de/quellen/ 124,241 0.49
19 /cq-dl/teil2/ 115,376 0.46
20 /gavrasm/v03/ 99,078 0.39
21 /gavrasm/v04/ 92,781 0.37
22 /gavrasm/v07/ 81,701 0.33
23 /gavrasm/old/v07/ 76,843 0.31
24 /gavrasm/v02/ 76,542 0.30
25 /gavrasm/v01/ 55,930 0.22
Sum 25,108,490 100.00

To top of page

Top 25 of 4166 requested files , sorted by number of files

N requested files times %


1 /avr_gra/RingLogo.jpg 90,910 5.88
2 /avr_gra/stk_lcd.jpg 70,675 4.57
3 /index.html 58,900 3.81
4 /avr_2313.gif 51,177 3.31
5 /avr-asm-tutorial.gif 50,629 3.27
6 /avr_de/index.html 42,958 2.78
7 /avr_en/index.html 38,207 2.47
8 /avr_gra/2313.gif 32,599 2.11
9 /avr_gra/screenshot.gif 23,149 1.50
10 /avr_gra/exp2313.gif 21,680 1.40
11 /avr_gra/avr_isp.gif 20,658 1.34
12 /avr_gra/8515.jpg 20,638 1.33
13 /avr_gra/exp_2313.jpg 20,569 1.33
14 /avr_gra/isp6pin.gif 20,559 1.33
15 /avr_gra/avr_isp.jpg 20,519 1.33
16 /avr_gra/isp10pin.gif 20,513 1.33
17 /avr_gra/exp2313g.jpg 20,355 1.32
/avr_en/beginner/RIGHT.
18 19,957 1.29
html
19 /avr_en/beginner/index.html 19,193 1.24
20 /avr_en/beginner/LEFT.html 18,296 1.18
21 /avr_de/beginner/rechts.html 16,629 1.07
22 /avr_de/beginner/index.html 15,823 1.02
23 /avr_de/beginner/links.html 15,517 1.00
24 /favicon.ico 14,029 0.91
25 /avr_gra/AT90S8515.jpg 13,677 0.88
Sum 1,547,301 100.00

To top of page

Top 25 of 4166 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_en.zip 6,024,415 23.99
2 /avr_de.zip 4,842,439 19.29
3 /beginner_de.pdf 1,219,331 4.86
4 /avr_2313.gif 779,623 3.11
5 /avr_de/index.html 439,373 1.75
6 /avr_en/index.html 377,649 1.50
7 /avr_gra/exp2313.gif 328,734 1.31
8 /avr_gra/exp2313g.jpg 247,556 0.99
9 /avr_gra/pwm_simul.jpg 242,980 0.97
10 /index.html 232,448 0.93
11 /avr_gra/avr_isp.jpg 200,059 0.80
12 /avr_gra/stk_lcd.jpg 190,460 0.76
13 /avr_gra/2313.gif 184,444 0.73
14 /avr_gra/AT90S8515.jpg 178,507 0.71
15 /avr-asm-tutorial.gif 154,592 0.62
16 /avr_en/beginner/JUMP.html 144,708 0.58
17 /avr_de/dcf77uhr.html 143,909 0.57
18 /avr_de/beginner/sprung.html 138,543 0.55
19 /gavrasm/gavrasmw/gavrasmW.zip 133,378 0.53
20 /avr_en/beginner/RIGHT.html 119,070 0.47
21 /cq_dl.zip 115,059 0.46
22 /avr_de/beginner/rechnen.html 106,809 0.43
23 /avr_en/beginner/CALC.html 104,048 0.41
24 /avr_gra/st4_1.gif 95,903 0.38
/avr_en/beginner/COMMANDS.
25 94,594 0.38
html
Sum 25,108,490 100.00

To top of page

Top 25 of 3359 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 58,900 9.27
2 /avr_de/index.html 42,958 6.76
3 /avr_en/index.html 38,207 6.01
4 /avr_en/beginner/RIGHT.html 19,957 3.14
5 /avr_en/beginner/index.html 19,193 3.02
6 /avr_en/beginner/LEFT.html 18,296 2.88
7 /avr_de/beginner/rechts.html 16,629 2.62
8 /avr_de/beginner/index.html 15,823 2.49
9 /avr_de/beginner/links.html 15,517 2.44
/avr_en/beginner/HARDWARE.
10 12,000 1.89
html
11 /avr_de/beginner/hardware.html 10,294 1.62
12 /avr_en/beginner/TOOLS.html 8,796 1.38
13 /avr_de/beginner/werkzeuge.html 7,926 1.25
14 /avr_en/beginner/REGISTER.html 7,572 1.19
15 /gavrasm/index_de.html 7,326 1.15
16 /avr_en/AVR_TUT.html 7,174 1.13
17 /avr_de/avr_tut.html 7,125 1.12
18 /avr_en/beginner/JUMP.html 6,961 1.10
19 /avr_de/beginner/register.html 6,207 0.98
20 /avr_en/beginner/PORTS.html 6,052 0.95
21 /avr_de/beginner/sprung.html 5,805 0.91
22 /avr_de/beginner/ports.html 5,639 0.89
23 /avr_en/calc/index.html 5,601 0.88
24 /cq-dl/teil1/index.html 5,513 0.87
25 /avr_de/rechnen/index.html 5,186 0.82
Sum 635,212 100.00

To top of page

Top 25 of 3359 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 439,373 7.18
2 /avr_en/index.html 377,649 6.17
3 /index.html 232,448 3.80
4 /avr_en/beginner/JUMP.html 144,708 2.36
5 /avr_de/dcf77uhr.html 143,909 2.35
6 /avr_de/beginner/sprung.html 138,543 2.26
7 /avr_en/beginner/RIGHT.html 119,070 1.95
8 /avr_de/beginner/rechnen.html 106,809 1.75
9 /avr_en/beginner/CALC.html 104,048 1.70
/avr_en/beginner/COMMANDS.
10 94,594 1.55
html
11 /avr_en/beginner/PDETAIL.html 88,713 1.45
12 /avr_en/beginner/TOOLS.html 88,426 1.44
13 /avr_de/beginner/rechts.html 88,391 1.44
14 /avr_de/beginner/werkzeuge.html 82,280 1.34
15 /avr_de/beginner/commands.html 81,340 1.33
16 /avr_en/beginner/REGISTER.html 80,387 1.31
/avr_en/beginner/HARDWARE.
17 79,776 1.30
html
18 /avr_de/beginner/pdetail.html 78,303 1.28
19 /cq-dl/teil4/index.html 77,569 1.27
20 /avr_en/calc/CONVERT.html 67,801 1.11
21 /avr_de/beginner/hardware.html 65,403 1.07
22 /avr_en/CLOCK.html 65,316 1.07
23 /avr_de/beginner/ports.html 60,850 0.99
24 /avr_en/beginner/PORTS.html 60,190 0.98
25 /avr_de/beginner/register.html 59,047 0.96
Sum 6,119,727 100.00

To top of page

Top 25 of 84 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 90,870 28.05
2 /avr_gra/stk_lcd.jpg 70,664 21.81
3 /avr_gra/8515.jpg 20,618 6.36
4 /avr_gra/exp_2313.jpg 20,569 6.35
5 /avr_gra/avr_isp.jpg 20,519 6.33
6 /avr_gra/exp2313g.jpg 20,336 6.28
/avr_gra/AT90S8515.
7 13,673 4.22
jpg
8 /avr_gra/apps.jpg 8,007 2.47
9 /avr_gra/stk200lcd.jpg 7,779 2.40
10 /cq-dl/exp2323.jpg 7,257 2.24
11 /avr_gra/stk200.jpg 5,949 1.84
12 /avr_gra/pwm_simul.jpg 4,669 1.44
13 /avr_gra/adc8conn.jpg 4,617 1.43
14 /avr_gra/stk_ram.jpg 4,578 1.41
15 /cq-dl/teil4/stk200.jpg 4,485 1.38
16 /cq-dl/teil3/max232.jpg 4,420 1.36
17 /avr_gra/sio_conn.jpg 3,149 0.97
18 /avr_gra/remote.jpg 3,038 0.94
19 /avr_gra/lcd_conn.jpg 3,016 0.93
20 /avr_gra/lcd_board.jpg 3,011 0.93
21 /avr_gra/pwg.jpg 2,125 0.66
22 /spicons/notfound.jpg 300 0.09
23 /spicons/gforbidden.jpg 208 0.06
24 /spicons/unknown.jpg 5 0.00
/avr_en/images/granit.
25 4 0.00
jpg
Sum 323,945 100.00

To top of page

Top 25 of 234 GIF-files , sorted by number of files

N GIF-files times %
1 /avr_2313.gif 51,156 13.08
2 /avr-asm-tutorial.gif 50,624 12.95
3 /avr_gra/2313.gif 32,588 8.33
/avr_gra/screenshot.
4 23,143 5.92
gif
5 /avr_gra/exp2313.gif 21,677 5.54
6 /avr_gra/avr_isp.gif 20,657 5.28
7 /avr_gra/isp6pin.gif 20,557 5.26
8 /avr_gra/isp10pin.gif 20,513 5.25
9 /gavrasm/gavrasm.gif 12,574 3.22
10 /avr_gra/lcd4conn.gif 8,364 2.14
11 /avr_gra/sram.gif 7,876 2.01
12 /avr_gra/ROR.gif 6,190 1.58
13 /avr_gra/ROL.gif 6,075 1.55
14 /cq-dl/teil1/2323a.gif 5,221 1.34
15 /cq-dl/teil1/2313a.gif 5,189 1.33
16 /avr_gra/adc8.gif 4,683 1.20
17 /avr_gra/adc8_hard.gif 4,667 1.19
18 /avr_gra/adc8_int.gif 4,628 1.18
19 /cq-dl/teil3/isp.gif 4,436 1.13
20 /avr_gra/wavrasm.gif 3,916 1.00
21 /avr_gra/assemble.gif 3,323 0.85
22 /avr_gra/isp.gif 3,105 0.79
/avr_gra/pcm2pwg4.
23 3,026 0.77
gif
24 /avr_gra/studio.gif 2,735 0.70
25 /avr_gra/eingabe.gif 2,632 0.67
Sum 391,044 100.00

To top of page

Top 25 of 266 entry pages , sorted by number of files

N entry pages times %


1 /index.html 23,219 26.44
2 /avr_de/index.html 7,479 8.52
3 /avr_en/index.html 7,154 8.15
4 /avr_de/beginner/index.html 2,301 2.62
5 /avr_en/beginner/index.html 2,295 2.61
6 /avr_en/beginner/HARDWARE.html 2,244 2.56
7 /avr_en/beginner/TOOLS.html 1,958 2.23
8 /avr_de/beginner/hardware.html 1,689 1.92
9 /avr_de/beginner/werkzeuge.html 1,500 1.71
10 /avr_en/calc/index.html 1,285 1.46
11 /avr_en/calc/CONVERSION.html 1,171 1.33
12 /avr_de/rechnen/index.html 1,145 1.30
13 /avr_en/calc/DIVISION.html 1,134 1.29
14 /avr_de/rechnen/konversion.html 1,071 1.22
/avr_en/calc/MULTIPLICATION.
15 929 1.06
html
16 /avr_en/calc/CONVERT.html 900 1.02
17 /avr_en/TESTLCD.html 827 0.94
18 /gavrasm/index_de.html 821 0.93
19 /cq-dl/teil4/index.html 739 0.84
20 /avr_de/beginner/rechnen.html 737 0.84
21 /avr_de/testram.html 708 0.81
22 /avr_de/beginner/pdetail.html 688 0.78
23 /avr_de/dcf77uhr.html 645 0.73
24 /avr_en/beginner/RIGHT.html 644 0.73
25 /avr_de/rechnen/konvert.html 596 0.68
Sum 87,822 100.00

To top of page

Top 25 of 423 cheat pages , sorted by number of files

N cheat pages times %


1 /index.html 12,994 13.12
2 /avr_de/index.html 7,166 7.23
3 /avr_en/index.html 6,668 6.73
4 6,043 6.10
5 /avr_en/beginner/HARDWARE.html 2,789 2.82
6 /avr_de/beginner/hardware.html 2,470 2.49
7 /avr_en/beginner/TOOLS.html 2,138 2.16
8 /avr_en/calc/CONVERT.html 1,848 1.87
9 /avr_en/beginner/RIGHT.html 1,785 1.80
10 /avr_de/beginner/werkzeuge.html 1,784 1.80
11 /avr_de/beginner/rechts.html 1,591 1.61
12 /gavrasm/index_de.html 1,331 1.34
13 /cq-dl/teil4/index.html 1,273 1.28
14 /avr_de/rechnen/konvert.html 1,186 1.20
15 /avr_de/beginner/rechnen.html 1,116 1.13
16 /avr_en/calc/DIVISION.html 1,062 1.07
/avr_en/calc/MULTIPLICATION.
17 1,060 1.07
html
18 /avr_en/beginner/JUMP.html 1,011 1.02
19 /avr_de/beginner/sprung.html 999 1.01
20 /cq-dl/teil3/index.html 961 0.97
21 /cq-dl/teil1/index.html 946 0.95
22 /avr_en/calc/CONVERSION.html 907 0.92
23 /avr_en/beginner/REGISTER.html 897 0.91
24 /avr_de/lcd4_500.html 869 0.88
25 /avr_de/rechnen/konversion.html 840 0.85
Sum 99,073 100.00

To top of page

Top 25 of 462 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 51,273 13.52
2 /avr_en/index.html 33,901 8.94
3 /avr_en/beginner/index.html 31,143 8.21
4 / 27,756 7.32
5 /avr_de/beginner/index.html 26,189 6.90
6 /avr_en/beginner/RIGHT.html 20,786 5.48
7 /avr_en/beginner/LEFT.html 19,415 5.12
8 /avr_de/beginner/links.html 18,653 4.92
9 /avr_de/beginner/rechts.html 14,976 3.95
10 /avr_en/ 14,006 3.69
11 /avr_de/ 10,900 2.87
12 /avr_en/AVR_TUT.html 5,950 1.57
13 /index.html 5,839 1.54
14 /weblox_en/index.html 5,719 1.51
15 /avr_de/avr_tut.html 5,667 1.49
16 /weblox_de/index.html 5,652 1.49
17 /avr_en/calc/index.html 3,408 0.90
18 /avr_de/rechnen/index.html 3,268 0.86
19 /avr_en/beginner/ 3,091 0.81
20 /avr_de/apps.html 2,475 0.65
21 /avr_en/AVR_SOFT.html 2,454 0.65
22 /avr_en/APPS.html 2,402 0.63
23 /avr_de/beginner/commands.html 2,335 0.62
/avr_en/beginner/COMMANDS.
24 2,246 0.59
html
25 /avr_en/calc/CONVERSION.html 2,156 0.57
Sum 379,317 100.00

To top of page

Top 25 of 3256 external referrers , sorted by number of files

N external referrers times %


1 - 144,751 83.92
2 http://www.mikrocontroller.net/links.htm 2,191 1.27
3 http://www.rowalt.de/mc/avr/linksd.htm 771 0.45
4 http://www.lug-kiel.de/links/details/f_avr.html 639 0.37
5 http://www.iptel-now.de/HOWTO/ATMEL/atmel.html 572 0.33
6 http://www.qsl.net/zl1bpu/micro/ENV/ENV.htm 501 0.29
7 http://www.lug-kiel.de/links/micros.html 480 0.28
8 http://arne.rossius.bei.t-online.de/schalt/mikro/avrkurs.htm 457 0.26
9 http://home.wanadoo.nl/electro1/avr/avrlinks.htm 447 0.26
10 http://www.raw-syndicate.us/rubriken/private_elektronik.html 428 0.25
11 http://matthieu.benoit.free.fr/avr.htm 392 0.23
12 http://katalogi.iele.polsl.gliwice.pl/linki.php 375 0.22
13 http://home.arcor.de/arnerossius/schalt/mikro/avrkurs.htm 368 0.21
14 http://www.raw-links.de/rubriken/private_elektronik.html 362 0.21
15 [unknown origin] 320 0.19
http://www.eg3.com/WebID/embedded/avr/blank/tutorial/a-z.
16 299 0.17
htm
17 http://r.webring.com/hub?ring=avr 298 0.17
18 http://www.mikrocontroller.net/forum/read-4-16376.html 292 0.17
19 289 0.17
20 http://r.webring.com/hub?sid=&ring=avr&id=&list 260 0.15
21 http://www.elektor.de/links/details/0303.htm 253 0.15
22 http://www.eg3.com/WebID/embedded/avr/blank/book/a-z.htm 239 0.14
23 http://www.bol.ucla.edu/~frank/avr.htm 224 0.13
24 http://mserv.rrzn.uni-hannover.de/cgi-bin/meta/meta.ger1 217 0.13
25 http://www.mikrocontroller.net/tutorial/equipment.htm 215 0.12
Sum 172,477 100.00

To top of page

Top 25 of 498 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 32,120 38.76
2 http://www.google.com 21,311 25.72
3 http://search.yahoo.com 3,733 4.50
4 http://www.google.at 2,652 3.20
5 http://www.google.ca 2,078 2.51
6 http://www.google.ch 1,579 1.91
7 http://search.msn.com 1,231 1.49
8 http://www.google.nl 1,188 1.43
9 http://www.google.com.au 1,066 1.29
10 http://www.google.pl 1,055 1.27
11 http://www.altavista.com 734 0.89
12 http://www.google.it 722 0.87
13 http://www.google.fi 666 0.80
14 http://www.google.fr 664 0.80
15 http://www.google.com.br 598 0.72
16 http://www.google.co.uk 584 0.70
17 http://www.google.be 564 0.68
http://de.search.yahoo.
18 452 0.55
com
19 http://www.google.co.in 433 0.52
http://www.google.com.
20 413 0.50
mx
21 http://www.google.com.gr 394 0.48
22 http://www.google.co.nz 336 0.41
23 http://www.google.se 327 0.39
24 http://www.google.pt 320 0.39
25 http://www.google.co.kr 316 0.38
Sum 82,865 100.00

To top of page

Top 25 of 38644 search strings , sorted by number of files

N search strings times %


1 assembler tutorial 2,029 2.45
2 avr 1,788 2.16
3 avr tutorial 1,659 2.00
4 avr assembler 851 1.03
5 AVR 791 0.95
6 binary division 774 0.93
7 binary multiplication 575 0.69
8 assembler 497 0.60
9 asm tutorial 479 0.58
10 stk500 393 0.47
11 wavrasm 325 0.39
12 mikrokontroller 273 0.33
13 ram testen 269 0.32
14 263 0.32
15 assembler lernen 263 0.32
assembler
16 262 0.32
programmierung
17 binary calculations 259 0.31
18 atmel tutorial 253 0.31
19 AVR tutorial 249 0.30
20 avr asm 239 0.29
21 assembly programing 205 0.25
22 avr assembler tutorial 204 0.25
23 Assembler Tutorial 203 0.24
24 STK500 168 0.20
25 rechteckgenerator 166 0.20
Sum 82,865 100.00

To top of page

Top 12 of 12 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 1,200,067 77.56
2 304 Not changed 253,654 16.39
3 xxx Unknown error 57,102 3.69
4 206 Partial information 24,437 1.58
5 404 File not found 5,693 0.37
6 301 Permanently moved 3,435 0.22
7 300 Multiple choices 1,928 0.12
8 403 Forbidden 876 0.06
9 500 Internal error 87 0.01
10 405 Method not allowed 15 0.00
11 401 Not authorized 5 0.00

http://www.avr-asm-tutorial.net/weblox_en/2003y.html (1 of 2)1/20/2009 8:05:45 PM


Weblog statistic for http://www.avr-asm-tutorial.net

12 501 Not implemented 2 0.00


Sum 1,547,301 100.00

To top of page

Top 25 of 2406 files not found , sorted by number of files

N files not found times %


/MSOffice/cltreq.asp?
1 420 7.38
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
2 /_vti_inf.html 318 5.59
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
3 20la 114 2.00
nguage_files/LEFT.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
4 20AVR-Assemble 90 1.58
r-Dateien/links.htm
5 /gavrasm/ReadMe.Txt 73 1.28
6 /gavrasm/LiesMich.Txt 66 1.16
7 /gavrasm/gavrasmi.html 62 1.09
/MSOffice/cltreq.asp?
8 52 0.91
UL=1&ACT=4&BUILD=4219&STRMVER=4&CAPREQ=0
9 /gavrasm/v01/ReadMe.Txt 27 0.47
10 /rechnen/index.html 20 0.35
11 /avr_de/avr_adc8.html 20 0.35
12 /avr_en/calc/CONVERT.html 20 0.35
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
13 20AVR-Assemble 18 0.32
r2-Dateien/links.htm
14 /weblox_de/TD 18 0.32
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
15 20la 18 0.32
nguage2_files/LEFT.htm
16 /weblox_en/TD 16 0.28
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
17 20la 16 0.28
nguage1_files/LEFT.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
18 20AVR-Assemble 16 0.28
r5-Dateien/links.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
19 20AVR-Assemble 16 0.28
r3-Dateien/links.htm
20 /avr_en/source/TEST1.asm 15 0.26
21 /gavrasm/v03/LiesMich.Txt 15 0.26
22 /gavrasm/v02/LiesMich.Txt 15 0.26
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
23 20AVR-Assemble 14 0.25
r4-Dateien/links.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
24 20la 14 0.25
nguage3_files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
25 20la 14 0.25
nguage7_files/LEFT.htm
Sum 5,693 100.00

To top of page

Top 25 of 598 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 1,225,346 79.19
2 Mozilla/5.0 126,235 8.16
3 Mozilla/4.5 18,512 1.20
4 Mozilla/3.0 14,505 0.94
5 Mozilla/3.01 10,788 0.70
6 WebZIP/5.0 7,841 0.51
7 Xaldon 7,123 0.46
8 Mozilla/4.7 6,492 0.42
9 Teleport Pro/1.29 6,482 0.42
10 Scooter/3.3_SF 6,027 0.39
11 Teleport 5,324 0.34
12 - 5,028 0.32
13 Mozilla/4.75 4,506 0.29
14 Googlebot/2.1 4,181 0.27
15 Offline 4,148 0.27
16 Mozilla/4.78 3,890 0.25
17 Opera/7.11 3,271 0.21
18 Wget/1.8.2 2,293 0.15
Web
19 2,280 0.15
Downloader/3.0
20 Mozilla/4.79 2,228 0.14
21 Opera/6.05 1,998 0.13
22 Scooter/3.2 1,965 0.13
23 WebStripper/2.10 1,925 0.12
24 WebReaper 1,854 0.12
25 WebCopier v3.3 1,839 0.12
Sum 1,547,301 100.00

To top of page

Top 25 of 390 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 783,507 50.64
2 unknown 196,862 12.72
3 MSIE 5.0 167,531 10.83
4 MSIE 5.5 142,997 9.24
5 MSIE 5.01 111,038 7.18
6 HTTrack 3.0x 16,546 1.07
7 Netscape/7.0 8,110 0.52
8 Netscape/7.01 6,756 0.44
9 Pro/1.29 6,482 0.42
10 HTTPClient 1.0 6,435 0.42
11 MSIE 5.00 6,286 0.41
12 Konqueror/3.1 6,159 0.40
13 Netscape/7.02 6,080 0.39
14 MSIE 4.01 4,859 0.31
15 WebCapture 2.0 4,751 0.31
16 Netscape/7.1 4,663 0.30
17 AOL 7.0 4,386 0.28
18 Macintosh 3,680 0.24
19 Opera/7.11 3,271 0.21
20 sun4u 2,613 0.17
21 AOL 8.0 2,350 0.15
22 Downloader/3.0 2,280 0.15
23 C-CCK-MCD DT 2,073 0.13
24 Opera/6.05 2,009 0.13
25 MSIE 6.0b 1,996 0.13
Sum 1,547,301 100.00

To top of page

Top 25 of 287 operating systems , sorted by number of files

N operating systems times %


1 Windows 98 412,192 26.64
2 Windows NT 5.1 410,905 26.56
3 Windows NT 5.0 334,246 21.60
4 unknown 141,357 9.14
5 Windows 74,346 4.80
6 Windows NT 4.0 43,219 2.79
7 Linux i686 27,073 1.75
8 Windows 95 16,086 1.04
9 Windows NT 13,401 0.87
10 Win95 9,957 0.64
11 Linux 9,246 0.60
12 WinNT 8,355 0.54
13 Windows 2000 6,253 0.40
14 Win98 5,574 0.36
15 Windows XP 5,260 0.34
16 Macintosh 3,791 0.25
17 Windows NT 5.2 2,504 0.16
18 Windows ME 2,486 0.16
19 Win32 1,560 0.10
20 SunOS sun4u 1,489 0.10
21 FreeBSD i386 1,112 0.07
22 Linux 2.4.20 i686 1,013 0.07
23 Linux i586 1,005 0.06
Linux 2.4.19-4GB
24 947 0.06
i686
25 SunOS 5.8 sun4u 784 0.05
Sum 1,547,301 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 52,115 3.37
2 01 39,840 2.57
3 02 29,909 1.93
4 03 26,153 1.69
5 04 23,094 1.49
6 05 22,723 1.47
7 06 24,195 1.56
8 07 35,168 2.27
9 08 53,592 3.46
10 09 57,712 3.73
11 10 71,404 4.61
12 11 82,843 5.35
13 12 90,670 5.86
14 13 86,677 5.60
15 14 89,206 5.77
16 15 88,826 5.74
17 16 84,944 5.49
18 17 84,714 5.47
19 18 81,386 5.26
20 19 81,634 5.28
21 20 92,046 5.95
22 21 85,285 5.51
23 22 86,971 5.62
24 23 76,194 4.92
Sum 1,547,301 100.00

To top of page

Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2003y.html (2 of 2)1/20/2009 8:05:45 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2002y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2002

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 64983 IPs and host names , sorted by number of files

N IPs and host names times %


1 217.24.160.76=proxy1.marka.net.ua 4,908 0.50
2 64.152.75.20=trek13.sv.av.com 4,664 0.47
3 213.148.160.96=(not found) 3,547 0.36
4 64.157.224.127=sync27.avantgo.com 2,304 0.23
5 64.157.224.128=sync28.avantgo.com 2,011 0.20
6 64.157.224.106=sync06.avantgo.com 2,002 0.20
7 64.157.224.101=sync01.avantgo.com 1,986 0.20
8 194.94.233.28=pcmirm.ipp-hgw.mpg.de 1,934 0.20
9 64.157.224.123=sync23.avantgo.com 1,894 0.19
10 64.157.224.130=sync30.avantgo.com 1,893 0.19
66.77.73.150=cr011r01.sac2.fastsearch.
11 1,857 0.19
net
12 64.157.224.110=sync10.avantgo.com 1,807 0.18
13 64.157.224.105=sync05.avantgo.com 1,784 0.18
14 64.157.224.114=sync14.avantgo.com 1,746 0.18
15 64.157.224.122=sync22.avantgo.com 1,723 0.18
16 64.157.224.109=sync09.avantgo.com 1,665 0.17
17 64.157.224.115=sync15.avantgo.com 1,588 0.16
18 64.157.224.107=sync07.avantgo.com 1,521 0.15
19 64.157.224.111=sync11.avantgo.com 1,510 0.15
20 62.132.15.253=stargate.sse-erfurt.de 1,453 0.15
21 64.157.224.112=sync12.avantgo.com 1,441 0.15
22 64.157.224.125=sync25.avantgo.com 1,429 0.15
23 194.138.37.36=proxy1.sbs.de 1,411 0.14
24 64.157.224.126=sync26.avantgo.com 1,296 0.13
25 64.157.224.121=sync21.avantgo.com 1,142 0.12
Sum 983,795 100.00

To top of page

Top 25 of 64983 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 64.157.224.127=sync27.avantgo.com 51,383 0.35
2 64.157.224.106=sync06.avantgo.com 48,771 0.33
3 64.157.224.101=sync01.avantgo.com 45,247 0.31
4 64.157.224.123=sync23.avantgo.com 35,129 0.24
5 64.157.224.122=sync22.avantgo.com 33,713 0.23
6 64.157.224.110=sync10.avantgo.com 33,631 0.23
7 64.157.224.114=sync14.avantgo.com 32,611 0.22
8 64.157.224.130=sync30.avantgo.com 32,456 0.22
217.82.255.128=pD952FF80.dip.t-dialin.
9 31,544 0.21
net
10 64.157.224.125=sync25.avantgo.com 30,522 0.21
11 64.157.224.105=sync05.avantgo.com 30,283 0.21
12 64.157.224.107=sync07.avantgo.com 30,224 0.21
13 64.157.224.111=sync11.avantgo.com 29,930 0.20
14 64.157.224.109=sync09.avantgo.com 28,741 0.20
15 64.157.224.115=sync15.avantgo.com 27,132 0.18
16 64.157.224.113=sync13.avantgo.com 27,100 0.18
17 130.83.244.129=ce1.hrz.tu-darmstadt.de 26,785 0.18
18 64.110.183.253=timoho.wintersat.com 26,632 0.18
19 152.118.24.3=netcache.ui.edu 26,436 0.18
20 64.157.224.128=sync28.avantgo.com 25,482 0.17
21 64.152.75.20=trek13.sv.av.com 25,044 0.17
22 194.65.14.68=pr2-ts.telepac.pt 24,204 0.16
23 64.157.224.126=sync26.avantgo.com 24,101 0.16
24 194.94.233.28=pcmirm.ipp-hgw.mpg.de 23,790 0.16
25 64.157.224.100=sync00.avantgo.com 22,578 0.15
Sum 14,718,534 100.00

To top of page

Top 25 of 11723 IPs and host names of multiple visitors , sorted by


number of visists

N IPs and host names of multiple visitors visits %


1 64.152.75.20=trek13.sv.av.com 463 0.74
2 193.7.255.244=(not found) 304 0.49
3 193.7.255.241=(not found) 223 0.36
4 209.73.164.50=bigip1a-snat.sv.av.com 205 0.33
5 194.138.37.36=proxy1.sbs.de 193 0.31
6 216.39.50.143=(not found) 179 0.29
7 64.152.75.46=buildrack20-old.sv.av.com 174 0.28
209.249.67.107=209.249.67.107.looksmart.
8 156 0.25
net
9 65.116.145.133=(not found) 153 0.25
10 193.110.40.150=srv-ze-robot10.blitzsuche.net 146 0.23
11 62.132.15.253=stargate.sse-erfurt.de 137 0.22
12 66.77.73.254=fpcr003.sac2.fastsearch.net 132 0.21
13 192.35.17.21=proxy2.netz.sbs.de 123 0.20
14 195.101.94.101=x1crawler2-1-0.x-echo.com 120 0.19
15 24.232.75.76=OL76-75.fibertel.com.ar 115 0.18
16 216.200.130.203=(not found) 114 0.18
17 66.77.73.150=cr011r01.sac2.fastsearch.net 108 0.17
66.77.73.219=cr016r01-test.sac2.fastsearch.
18 93 0.15
net
19 203.96.111.202=AKCF1.xtra.co.nz 92 0.15
20 202.49.5.18=border0.tekotago.ac.nz 90 0.14
21 217.110.40.82=(not found) 90 0.14
22 195.93.65.11=cache-fra-ab05.proxy.aol.com 90 0.14
23 216.239.35.4=(not found) 88 0.14
24 64.152.75.204=buildrack74.sv.av.com 88 0.14
25 213.224.83.19=ncnocm03.telenet-ops.be 87 0.14
Sum 62,343 100.00

To top of page

Top 25 of 157 countries of origin , sorted by number of files

N countries of origin times %


1 net 315,932 32.11
2 (unresolved) 178,108 18.10
3 com 140,321 14.26
4 Germany 110,186 11.20
5 Austria 27,207 2.77
6 Canada 21,695 2.21
7 Australia 14,959 1.52
8 Switzerland 14,451 1.47
9 Netherlands 13,863 1.41
10 Poland 12,551 1.28
11 Sweden 10,891 1.11
12 edu 8,517 0.87
13 Italy 8,358 0.85
14 France 7,267 0.74
15 Spain 6,742 0.69
16 Finland 6,270 0.64
17 Belgium 6,233 0.63
18 Ukraine 5,448 0.55
19 New Zealand 5,223 0.53
20 Czech Republic 4,793 0.49
21 Greece 4,710 0.48
22 United Kingdom 4,285 0.44
23 Brazil 3,858 0.39
24 Denmark 3,520 0.36
25 Norway 3,456 0.35
Sum 983,795 100.00

To top of page

Top 25 of 827 pathes , sorted by number of files

N pathes times %
1 /avr_gra/ 340,877 34.65
2 / 130,085 13.22
3 /avr_en/beginner/ 101,309 10.30
4 /avr_de/beginner/ 86,199 8.76
5 /avr_en/ 77,952 7.92
6 /avr_de/ 75,511 7.68
7 /avr_en/source/ 34,577 3.51
8 /avr_en/calc/ 25,894 2.63
9 /avr_de/quellen/ 22,512 2.29
10 /avr_de/rechnen/ 20,051 2.04
11 /cq-dl/teil1/ 11,714 1.19
12 /cq-dl/teil3/ 11,011 1.12
13 /cq-dl/teil4/ 10,389 1.06
14 /weblox_en/ 8,989 0.91
15 /cq-dl/ 8,107 0.82
16 /weblox_de/ 7,801 0.79
17 /cq-dl/teil2/ 5,910 0.60
18 /gavrasm/ 771 0.08
19 /spicons/ 711 0.07
20 /avr_de/cq-dl/ 680 0.07
21 /cgi-bin/ 248 0.03
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
22 20AVR-Assemble 200 0.02
r-Dateien/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
23 %20la 143 0.01
nguage_files/
24 /_vti_bin/ 84 0.01
25 /MSOffice/ 80 0.01
Sum 983,795 100.00

To top of page

Top 25 of 827 pathes , sorted by kbytes

N pathes kbytes %
1 / 8,013,357 54.44
2 /avr_gra/ 1,842,947 12.52
3 /avr_en/beginner/ 815,148 5.54
4 /avr_de/beginner/ 712,734 4.84
5 /weblox_en/ 554,377 3.77
6 /avr_de/ 543,631 3.69
7 /avr_en/ 525,797 3.57
8 /weblox_de/ 417,036 2.83
9 /avr_en/calc/ 322,169 2.19
10 /avr_de/rechnen/ 215,256 1.46
11 /cq-dl/teil4/ 161,609 1.10
12 /avr_en/source/ 149,325 1.01
13 /avr_de/quellen/ 119,266 0.81
14 /cq-dl/teil1/ 114,450 0.78
15 /cq-dl/teil3/ 75,951 0.52
16 /cq-dl/teil2/ 73,313 0.50
17 /cq-dl/ 37,377 0.25
18 /gavrasm/ 14,804 0.10
19 /spicons/ 2,734 0.02
20 /avr_en/../ 1,548 0.01
21 /avr_de/cq-dl/ 604 0.00
22 /cgi-bin/ 440 0.00
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
23 20AVR-Assemble 400 0.00
r-Dateien/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%
24 20assembler%20la 286 0.00
nguage_files/
25 /_vti_bin/ 164 0.00
Sum 14,718,534 100.00

To top of page

Top 25 of 2432 requested files , sorted by number of files

N requested files times %


1 /avr_gra/RingLogo.jpg 62,268 6.33
2 /avr_gra/stk_lcd.jpg 49,963 5.08
3 /index.html 39,155 3.98
4 /avr_2313.gif 33,451 3.40
5 /avr-asm-tutorial.gif 32,876 3.34
6 /avr_de/index.html 29,608 3.01
7 /avr_en/index.html 27,289 2.77
8 /avr_gra/2313.gif 23,134 2.35
9 /avr_gra/screenshot.gif 18,218 1.85
10 /avr_en/beginner/RIGHT.html 14,824 1.51
11 /avr_en/beginner/index.html 14,011 1.42
12 /avr_en/beginner/LEFT.html 13,332 1.36
13 /avr_gra/8515.jpg 12,729 1.29
14 /avr_de/beginner/index.html 12,405 1.26
15 /avr_de/beginner/rechts.html 11,794 1.20
16 /avr_de/beginner/links.html 10,972 1.12
17 /avr_gra/AT90S8515.jpg 10,322 1.05
18 /avr_gra/clock.pdf 9,073 0.92
19 /avr_en/beginner/TOOLS.html 7,534 0.77
20 /favicon.ico 7,179 0.73
21 /avr_gra/apps.jpg 7,176 0.73
/avr_de/beginner/werkzeuge.
22 7,040 0.72
html
23 /avr_gra/avr_isp.gif 6,945 0.71
24 /avr_gra/exp2313.gif 6,940 0.71
25 /avr_gra/isp6pin.gif 6,910 0.70
Sum 983,795 100.00

To top of page

Top 25 of 2432 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_en.zip 3,785,542 25.72
2 /avr_de.zip 3,326,024 22.60
3 /avr_2313.gif 517,295 3.51
4 /avr_de/index.html 247,472 1.68
5 /avr_en/index.html 218,976 1.49
6 /index.html 137,501 0.93
7 /avr_gra/stk_lcd.jpg 136,724 0.93
8 /avr_gra/AT90S8515.jpg 135,338 0.92
9 /avr_gra/2313.gif 132,735 0.90
10 /avr_en/beginner/JUMP.html 112,589 0.76
11 /avr_de/beginner/sprung.html 107,746 0.73
12 /avr-asm-tutorial.gif 101,338 0.69
13 /cq_dl.zip 91,477 0.62
14 /avr_en/beginner/CALC.html 89,045 0.60
15 /avr_gra/clock.pdf 82,288 0.56
16 /avr_gra/exp2313g.jpg 81,879 0.56
17 /avr_en/beginner/RIGHT.html 81,824 0.56
/avr_en/beginner/COMMANDS.
18 77,925 0.53
html
19 /avr_en/beginner/TOOLS.html 74,127 0.50
20 /avr_de/dcf77uhr.html 73,925 0.50
21 /avr_de/beginner/rechnen.html 73,163 0.50
22 /avr_de/beginner/werkzeuge.html 71,564 0.49
23 /avr_en/beginner/PDETAIL.html 68,654 0.47
24 /avr_gra/avr_isp.jpg 66,225 0.45
25 /avr_gra/isp.gif 64,787 0.44
Sum 14,718,534 100.00

To top of page

Top 25 of 1839 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 39,155 8.68
2 /avr_de/index.html 29,608 6.57
3 /avr_en/index.html 27,289 6.05
4 /avr_en/beginner/RIGHT.html 14,824 3.29
5 /avr_en/beginner/index.html 14,011 3.11
6 /avr_en/beginner/LEFT.html 13,332 2.96
7 /avr_de/beginner/index.html 12,405 2.75
8 /avr_de/beginner/rechts.html 11,794 2.62
9 /avr_de/beginner/links.html 10,972 2.43
10 /avr_en/beginner/TOOLS.html 7,534 1.67
11 /avr_de/beginner/werkzeuge.html 7,040 1.56
12 /avr_en/AVR_TUT.html 6,092 1.35
13 /avr_en/beginner/REGISTER.html 5,964 1.32
14 /avr_en/beginner/JUMP.html 5,384 1.19
15 /avr_de/avr_tut.html 5,331 1.18
16 /avr_en/beginner/PORTS.html 4,880 1.08
17 /avr_en/beginner/WHY.html 4,814 1.07
18 /avr_de/apps.html 4,699 1.04
19 /avr_de/beginner/sprung.html 4,558 1.01
20 /avr_de/beginner/register.html 4,268 0.95
21 /avr_de/rechnen/index.html 4,244 0.94
/avr_en/beginner/COMMANDS.
22 4,183 0.93
html
23 /avr_de/beginner/ports.html 4,081 0.91
24 /avr_en/calc/index.html 4,029 0.89
25 /avr_en/beginner/SRAM.html 3,951 0.88
Sum 450,853 100.00

To top of page

Top 25 of 1839 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 247,472 6.00
2 /avr_en/index.html 218,976 5.31
3 /index.html 137,501 3.33
4 /avr_en/beginner/JUMP.html 112,589 2.73
5 /avr_de/beginner/sprung.html 107,746 2.61
6 /avr_en/beginner/CALC.html 89,045 2.16
7 /avr_en/beginner/RIGHT.html 81,824 1.98
/avr_en/beginner/COMMANDS.
8 77,925 1.89
html
9 /avr_en/beginner/TOOLS.html 74,127 1.80
10 /avr_de/dcf77uhr.html 73,925 1.79
11 /avr_de/beginner/rechnen.html 73,163 1.77
12 /avr_de/beginner/werkzeuge.html 71,564 1.74
13 /avr_en/beginner/PDETAIL.html 68,654 1.66
14 /avr_de/beginner/rechts.html 60,576 1.47
15 /avr_en/beginner/REGISTER.html 60,392 1.46
16 /avr_de/beginner/commands.html 57,387 1.39
17 /avr_de/beginner/pdetail.html 52,695 1.28
18 /avr_en/CLOCK.html 50,861 1.23
19 /avr_en/beginner/PORTS.html 49,114 1.19
20 /cq-dl/teil4/index.html 49,017 1.19
21 /avr_en/calc/CONVERT.html 48,502 1.18
22 /avr_en/beginner/SRAM.html 44,251 1.07
23 /avr_de/beginner/ports.html 43,901 1.06
24 /avr_en/beginner/LEFT.html 40,197 0.97
25 /avr_de/beginner/register.html 39,229 0.95
Sum 4,123,778 100.00

To top of page

Top 25 of 52 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 62,257 30.88
2 /avr_gra/stk_lcd.jpg 49,958 24.78
3 /avr_gra/8515.jpg 12,727 6.31
4 /avr_gra/AT90S8515.jpg 10,319 5.12
5 /avr_gra/apps.jpg 7,176 3.56
6 /avr_gra/avr_isp.jpg 6,904 3.42
7 /avr_gra/exp_2313.jpg 6,872 3.41
8 /avr_gra/exp2313g.jpg 6,835 3.39
9 /avr_gra/stk200lcd.jpg 6,596 3.27
10 /avr_gra/stk200.jpg 5,247 2.60
11 /cq-dl/exp2323.jpg 4,786 2.37
12 /avr_gra/stk_ram.jpg 4,288 2.13
13 /avr_gra/sio_conn.jpg 2,966 1.47
14 /cq-dl/teil4/stk200.jpg 2,795 1.39
15 /avr_gra/remote.jpg 2,659 1.32
16 /cq-dl/teil3/max232.jpg 2,598 1.29
17 /avr_gra/lcd_conn.jpg 2,268 1.12
18 /avr_gra/lcd_board.jpg 2,256 1.12
19 /avr_gra/pwg.jpg 1,882 0.93
20 /spicons/notfound.jpg 112 0.06
21 /spicons/gforbidden.jpg 66 0.03
22 /avr_en/../avr_gra/stk_lcd.jpg 4 0.00
23 /avr_en/../avr_gra/RingLogo.jpg 4 0.00
24 /cq-dl/teil1/exp2323.jpg 2 0.00
http://www.avr-asm-tutorial.net/avr_gra/RingLogo.
25 2 0.00
jpg
Sum 201,613 100.00

To top of page

Top 25 of 137 GIF-files , sorted by number of files

N GIF-files times %
1 /avr_2313.gif 33,434 14.36
2 /avr-asm-tutorial.gif 32,875 14.12
3 /avr_gra/2313.gif 23,092 9.92
/avr_gra/screenshot.
4 18,206 7.82
gif
5 /avr_gra/avr_isp.gif 6,945 2.98
6 /avr_gra/exp2313.gif 6,940 2.98
7 /avr_gra/isp6pin.gif 6,910 2.97
8 /avr_gra/isp10pin.gif 6,881 2.96
9 /avr_gra/sram.gif 5,751 2.47
10 /avr_gra/lcd4conn.gif 5,416 2.33
11 /avr_gra/ROR.gif 4,445 1.91
12 /avr_gra/ROL.gif 4,438 1.91
13 /avr_gra/wavrasm.gif 3,834 1.65
14 /cq-dl/teil1/2323a.gif 3,575 1.54
15 /cq-dl/teil1/2313a.gif 3,559 1.53
16 /avr_gra/assemble.gif 3,175 1.36
17 /avr_gra/isp.gif 2,949 1.27
/avr_gra/pcm2pwg4.
18 2,842 1.22
gif
19 /avr_gra/studio.gif 2,754 1.18
20 /avr_gra/eingabe.gif 2,709 1.16
21 /avr_gra/silliksaar.gif 2,640 1.13
22 /cq-dl/teil3/isp.gif 2,610 1.12
23 /avr_gra/hex.gif 2,069 0.89
24 /avr_gra/options.gif 1,930 0.83
25 /avr_gra/view.gif 1,773 0.76
Sum 232,807 100.00

To top of page

Top 25 of 235 entry pages , sorted by number of files

N entry pages times %


1 /index.html 14,608 25.29
2 /avr_de/index.html 6,875 11.90
3 /avr_en/index.html 6,376 11.04
4 /avr_de/beginner/werkzeuge.html 1,245 2.16
5 /avr_en/beginner/TOOLS.html 1,206 2.09
6 /avr_en/beginner/index.html 1,114 1.93
7 /avr_de/beginner/index.html 1,105 1.91
8 /avr_en/calc/index.html 890 1.54
9 /avr_de/rechnen/index.html 864 1.50
10 /avr_de/rechnen/konversion.html 772 1.34
11 /avr_en/calc/CONVERSION.html 705 1.22
12 /avr_en/beginner/STUDIO352.html 634 1.10
/avr_en/calc/MULTIPLICATION.
13 631 1.09
html
14 /avr_en/calc/DIVISION.html 627 1.09
15 /avr_en/TESTLCD.html 574 0.99
16 /avr_de/beginner/rechnen.html 561 0.97
17 /avr_de/dcf77uhr.html 531 0.92
18 /avr_en/beginner/HARDWARE.html 524 0.91
19 /cq-dl/teil4/index.html 502 0.87
20 /avr_en/LCD4_500.html 479 0.83
21 /avr_en/calc/CONVERT.html 478 0.83
22 /avr_de/beginner/Warum.html 460 0.80
23 /avr_en/beginner/RIGHT.html 457 0.79
24 /avr_en/REMOTE.html 441 0.76
25 /avr_de/beginner/sprung.html 438 0.76
Sum 57,758 100.00

To top of page

Top 25 of 289 cheat pages , sorted by number of files

N cheat pages times %


1 /index.html 8,241 12.68
2 /avr_de/index.html 5,203 8.01
3 5,169 7.95
4 /avr_en/index.html 4,756 7.32
5 /avr_en/beginner/TOOLS.html 1,592 2.45
6 /avr_de/beginner/werkzeuge.html 1,493 2.30
7 /avr_en/beginner/RIGHT.html 1,213 1.87
8 /avr_en/calc/CONVERT.html 1,113 1.71
9 /avr_de/beginner/rechts.html 897 1.38
10 /avr_en/beginner/HARDWARE.html 850 1.31
11 /cq-dl/teil4/index.html 821 1.26
12 /avr_de/beginner/hardware.html 766 1.18
13 /avr_de/beginner/sprung.html 760 1.17
14 /avr_de/rechnen/konvert.html 741 1.14
15 /avr_de/beginner/rechnen.html 736 1.13
/avr_en/calc/MULTIPLICATION.
16 732 1.13
html
17 /avr_en/beginner/JUMP.html 723 1.11
18 /cq-dl/teil1/index.html 693 1.07
19 /avr_de/rechnen/konversion.html 692 1.06
20 /avr_en/calc/DIVISION.html 668 1.03
21 /avr_en/beginner/STUDIO352.html 657 1.01
22 /avr_de/dcf77uhr.html 657 1.01
23 /avr_en/beginner/REGISTER.html 648 1.00
24 /cq-dl/teil3/index.html 620 0.95
25 /avr_de/apps.html 620 0.95
Sum 64,983 100.00

To top of page

Top 25 of 418 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 36,409 12.32
2 /avr_en/index.html 35,732 12.09
3 /avr_en/beginner/index.html 23,429 7.93
4 /avr_en/beginner/RIGHT.html 20,814 7.04
5 /avr_de/beginner/index.html 18,096 6.12
6 / 17,036 5.76
7 /avr_de/beginner/rechts.html 14,388 4.87
8 /avr_en/beginner/LEFT.html 13,909 4.71
9 /avr_de/beginner/links.html 12,819 4.34
10 /avr_de/ 8,999 3.04
11 /avr_en/ 7,284 2.46
12 /weblox_en/index.html 6,692 2.26
13 /index.html 6,038 2.04
14 /avr_en/AVR_TUT.html 5,291 1.79
15 /weblox_de/index.html 5,037 1.70
16 /avr_de/avr_tut.html 4,188 1.42
17 /avr_en/AVR_SOFT.html 2,823 0.96
18 /avr_de/rechnen/index.html 2,673 0.90
19 /avr_en/AVR_HARD.html 2,640 0.89
20 /avr_de/apps.html 2,552 0.86
21 /avr_en/APPS.html 2,500 0.85
22 /avr_en/calc/index.html 1,931 0.65
/avr_en/beginner/COMMANDS.
23 1,881 0.64
html
24 /avr_de/avr_hard.html 1,852 0.63
25 /avr_de/avr_soft.html 1,849 0.63
Sum 295,541 100.00

To top of page

Top 25 of 1726 external referrers , sorted by number of files

N external referrers times %


1 - 85,691 81.47
2 http://www.mikrocontroller.net/links.htm 1,388 1.32
3 http://www.dg4fac.de/avr/avr_en/index.html 1,289 1.23
4 http://www.rowalt.de/mc/avr/linksd.htm 620 0.59
5 http://rawlinks.lunarpages.com/rubriken/private_elektronik.html 509 0.48
6 http://www.blitzsuche.de/ 494 0.47
http://www.speedy-conzales.com/cgi-bin/raw/server1/elektronik/elektron
7 491 0.47
ik.html
8 [unknown origin] 436 0.41
9 http://www.lug-kiel.de/links/micros.html 411 0.39
10 http://www.raw-server.to/elektronik/elektronik.html 376 0.36
11 http://www.dg4fac.de/avr/avr_de/index.html 374 0.36
12 http://www.qsl.net/zl1bpu/micro/ENV/ENV.htm 325 0.31
13 http://r.webring.com/hub?ring=avr&list&page=1 319 0.30
14 http://www.dg4fac.de/rechtsunten.html 260 0.25
15 http://www.rowalt.de/mc/ 248 0.24
16 http://www.dg4fac.de/avr/avr_de/ 243 0.23
17 http://r.webring.com/webring?ring=avr;list 236 0.22
18 http://www.iptel-now.de/HOWTO/ATMEL/atmel.html 234 0.22
19 http://home.t-online.de/home/Arne.Rossius/schalt/micro/avrkurs.htm 232 0.22
http://directory.google.com/Top/World/Deutsch/Computer/Hardware/
20 Mikroc 224 0.21
ontroller/
21 http://www.dg4fac.de/linksunten.html 207 0.20
22 http://mserv.rrzn.uni-hannover.de/cgi-bin/meta/meta.ger1 201 0.19
http://pub73.ezboard.com/fzackyfiles45879frm28.showMessage?
23 topicID=27. 194 0.18
topic
24 191 0.18
25 http://www.dg4fac.de/avr/avr_tut.html 184 0.17
Sum 105,175 100.00

To top of page

Top 25 of 368 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 17,825 35.64
2 http://www.google.com 16,401 32.80
3 http://google.yahoo.com 1,873 3.75
4 http://www.google.ca 1,485 2.97
5 http://www.google.at 1,286 2.57
6 http://www.google.ch 913 1.83
7 http://search.yahoo.com 908 1.82
8 http://www.altavista.com 642 1.28
9 http://www.google.nl 601 1.20
10 http://www.google.it 528 1.06
http://de.search.yahoo.
11 508 1.02
com
12 http://id-discussions.com 474 0.95
13 http://www.google.fr 448 0.90
14 http://search.msn.com 412 0.82
15 http://www.google.com.pl 331 0.66
16 http://www.google.be 294 0.59
17 http://suche.lycos.de 273 0.55
http://de.google.yahoo.
18 267 0.53
com
19 http://www.google.com.br 258 0.52
20 http://www.google.co.uk 257 0.51
21 http://www.google.co.nz 184 0.37
22 http://www.google.co.kr 182 0.36
23 http://suche.web.de 181 0.36
24 http://de.altavista.com 164 0.33
25 http://www.alltheweb.com 146 0.29
Sum 50,009 100.00

To top of page

Top 25 of 23891 search strings , sorted by number of files

N search strings times %


1 avr 974 1.95
2 avr tutorial 868 1.74
3 assembler tutorial 834 1.67
4 621 1.24
5 avr assembler 469 0.94
6 AVR 437 0.87
7 binary multiplication 431 0.86
8 binary division 422 0.84
9 stk500 360 0.72
10 asm tutorial 282 0.56
11 wavrasm 209 0.42
12 assembler lernen 188 0.38
13 atmel tutorial 182 0.36
14 assembler 174 0.35
15 atmel 163 0.33
16 STK500 161 0.32
17 assembly programing 160 0.32
18 rechteckgenerator 151 0.30
19 at90s2313 138 0.28
assembler
20 130 0.26
programmierung
21 ram testen 122 0.24
22 avr assembler tutorial 117 0.23
23 atmel avr tutorial 117 0.23
24 avr asm 113 0.23
25 Rechteckgenerator 112 0.22
Sum 50,009 100.00

To top of page

Top 11 of 11 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 791,262 80.43
2 304 Not changed 162,665 16.53
3 206 Partial information 14,472 1.47
4 xxx Unknown error 8,602 0.87
5 404 File not found 2,267 0.23
6 301 Permanently moved 2,144 0.22

http://www.avr-asm-tutorial.net/weblox_en/2002y.html (1 of 2)1/20/2009 8:06:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

7 300 ? 1,878 0.19


8 403 Forbidden 497 0.05
9 xxx Unknown error 4 0.00
10 xxx Unknown error 3 0.00
11 xxx Unknown error 1 0.00
Sum 983,795 100.00

To top of page

Top 25 of 1132 files not found , sorted by number of files

N files not found times %


/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
1 20AVR-Assemble 112 4.94
r-Dateien/links.htm
2 /_vti_inf.html 87 3.84
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
3 20la 84 3.71
nguage_files/LEFT.htm
/MSOffice/cltreq.asp?
4 77 3.40
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
5 20AVR-Assemble 28 1.24
r-Dateien/rechts.htm
6 /avr_gra/lcd4conn.gif 28 1.24
7 /rechnen/index.html 28 1.24
8 /cgi-bin/formmail.pl 27 1.19
9 /avr_en/TESTSINT.html 25 1.10
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
10 20la 19 0.84
nguage_files/LEFT.html
11 /weblox_de/TD 19 0.84
12 /weblox_en/TD 18 0.79
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
13 20AVR-Assemble 18 0.79
r-Dateien/links.html
14 /avr_de/cq-dl/index.html 17 0.75
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
15 20la 16 0.71
nguage2_files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
16 20la 15 0.66
nguage_files/RIGHT.htm
17 /cgi-bin/formmail.cgi 15 0.66
18 /avr_de/testsint.html 14 0.62
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
19 20AVR-Assemble 14 0.62
r2-Dateien/links.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
20 20AVR-Assemble 13 0.57
r1-Dateien/links.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
21 20AVR-Assemble 12 0.53
r-Dateien/register.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
22 20la 11 0.49
nguage3_files/LEFT.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
23 20AVR-Assemble 11 0.49
r3-Dateien/links.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
24 20la 10 0.44
nguage_pliki/LEFT.htm
25 /avr_de/quellen/bcdmath.asm 9 0.40
Sum 2,267 100.00

To top of page

Top 25 of 487 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 738,403 75.06
2 Mozilla/3.0 58,008 5.90
3 Mozilla/5.0 42,689 4.34
4 Mozilla/4.5 14,025 1.43
5 Mozilla/4.7 8,409 0.85
6 Mozilla/3.01 6,699 0.68
7 Mozilla/4.75 5,851 0.59
8 Mozilla/4.78 5,788 0.59
9 Mozilla/4.73 4,589 0.47
10 Scooter-W3.1.2 4,508 0.46
11 Offline 4,189 0.43
12 Teleport 3,900 0.40
13 Mozilla/4.79 3,694 0.38
Teleport
14 3,414 0.35
Pro/1.29
15 Mozilla/4.76 3,386 0.34
16 Mozilla/4.77 3,065 0.31
17 - 2,806 0.29
18 Mozilla/4.51 2,619 0.27
19 Xaldon 2,374 0.24
20 Opera/6.0 2,353 0.24
21 Wget/1.8.1 2,226 0.23
22 Googlebot/2.1 2,104 0.21
23 Wget/1.6 1,953 0.20
24 DA 5.0 1,753 0.18
25 Opera/6.01 1,622 0.16
Sum 983,795 100.00

To top of page

Top 25 of 368 browser versions , sorted by number of files

N browser versions times %


1 MSIE 6.0 340,954 34.66
2 unknown 170,455 17.33
3 MSIE 5.5 159,260 16.19
4 MSIE 5.0 115,565 11.75
5 MSIE 5.01 99,773 10.14
6 HTTrack 3.0x 10,131 1.03
7 MSIE 4.01 9,214 0.94
8 Netscape/7.0 4,317 0.44
9 C-CCK-MCD DT 3,932 0.40
10 MSIE 6.0b 3,637 0.37
11 Pro/1.29 3,414 0.35
12 WebCapture 2.0 3,240 0.33
13 AOL 7.0 3,222 0.33
14 sun4u 2,955 0.30
15 MSIE 5.00 2,556 0.26
16 Netscape6/6.2.1 2,455 0.25
17 Opera/6.0 2,353 0.24
18 WebCapture 1.0 2,322 0.24
19 HTTPClient 1.0 1,753 0.18
20 Pro/1.29.1590 1,705 0.17
21 Opera/6.01 1,622 0.16
22 C-CCK-MCD 1,591 0.16
23 Pro/1.29.1820 1,522 0.15
24 Netscape6/6.2 1,500 0.15
25 Konqueror/3 1,469 0.15
Sum 983,795 100.00

To top of page

Top 25 of 297 operating systems , sorted by number of files

N operating systems times %


1 Windows 98 316,943 32.22
2 Windows NT 5.0 198,347 20.16
3 Windows NT 5.1 146,936 14.94
4 unknown 133,793 13.60
5 Windows NT 4.0 36,625 3.72
6 Windows 27,077 2.75
7 Windows NT 21,102 2.14
8 Windows 95 19,491 1.98
9 Win98 14,512 1.48
10 WinNT 11,612 1.18
11 Win95 9,166 0.93
12 Linux i686 9,041 0.92
13 Windows 2000 8,982 0.91
14 Linux 4,799 0.49
15 Windows XP 4,637 0.47
16 Windows ME 1,621 0.16
17 Macintosh 1,495 0.15
18 SunOS 5.8 sun4u 1,486 0.15
19 Win32 1,102 0.11
20 X11 928 0.09
21 SunOS 5.7 sun4u 808 0.08
22 SunOS 5.6 sun4u 675 0.07
Linux 2.4.10-4GB
23 670 0.07
i686
24 Linux 2.4.18 i686 623 0.06
25 Linux i586 553 0.06
Sum 983,795 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 37,312 3.79
2 01 23,425 2.38
3 02 20,369 2.07
4 03 23,583 2.40
5 04 22,537 2.29
6 05 19,228 1.95
7 06 18,291 1.86
8 07 26,644 2.71
9 08 34,166 3.47
10 09 40,360 4.10
11 10 43,391 4.41
12 11 52,062 5.29
13 12 51,251 5.21
14 13 52,489 5.34
15 14 60,234 6.12
16 15 57,521 5.85
17 16 55,114 5.60
18 17 53,601 5.45
19 18 50,699 5.15
20 19 50,653 5.15
21 20 51,719 5.26
22 21 48,469 4.93
23 22 48,888 4.97
24 23 41,789 4.25
Sum 983,795 100.00

To top of page

Created with Weblox, version 0.9a, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2002y.html (2 of 2)1/20/2009 8:06:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Yearly sorted index ==> Log 2001y

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2001

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 2906 IPs and host names , sorted by number of files

N IPs and host names times %


1 194.65.14.77=pr7-ts.telepac.pt 646 1.69
2 194.88.125.61=p00-61.brus.online.be 368 0.97
3 209.83.89.250=(not found) 303 0.79
4 66.77.74.150=cr011r01.sac2.fastsearch.net 296 0.78
5 141.22.4.130=proxy.haw-hamburg.de 290 0.76
6 199.105.244.164=(not found) 272 0.71
7 12.239.17.47=12-239-17-47.client.attbi.com 272 0.71
8 209.73.162.20=trek13.sv.av.com 263 0.69
9 199.105.244.1=host1-199-244.cableaz.com 259 0.68
10 199.105.244.126=(not found) 258 0.68
11 212.185.223.121=pD4B9DF79.dip.t-dialin.net 231 0.61
12 62.104.220.91=sgt2-t6-2.mcbone.net 229 0.60
13 199.105.245.109=(not found) 228 0.60
14 145.254.249.171=dialin-145-254-249-171.arcor-ip.net 221 0.58
15 200.135.44.20=(not found) 217 0.57
16 193.170.87.120=(not found) 208 0.55
17 200.65.22.187=dup-200-65-22-187.prodigy.net.mx 203 0.53
18 192.35.17.132=p1fsc.netz.sbs.de 202 0.53
19 139.165.30.57=cs217.gw.ulg.ac.be 192 0.50
20 62.104.222.81=brm2-t1-2.mcbone.net 191 0.50
21 199.105.244.115=(not found) 185 0.49
22 212.191.170.237=nat-ld7.tvsat364.lodz.pl 173 0.45
23 61.73.155.96=(not found) 166 0.44
66.130.142.152=modemcable152.142-130-66.que.mc.videotron.
24 163 0.43
ca
25 80.135.216.214=p5087D8D6.dip.t-dialin.net 162 0.42
Sum 38,127 100.00

To top of page

Top 25 of 2906 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 194.65.14.77=pr7-ts.telepac.pt 11,609 1.86
2 199.105.244.1=host1-199-244.cableaz.com 7,111 1.14
3 209.83.89.250=(not found) 6,412 1.03
4 199.105.244.126=(not found) 5,940 0.95
5 212.185.223.121=pD4B9DF79.dip.t-dialin.net 4,782 0.77
6 12.239.17.47=12-239-17-47.client.attbi.com 4,685 0.75
7 212.164.1.44=ppp044.online.nsk.su 4,643 0.75
8 200.65.22.187=dup-200-65-22-187.prodigy.net.mx 4,249 0.68
9 139.165.30.57=cs217.gw.ulg.ac.be 3,785 0.61
10 62.104.212.66=ffm2-t2-1.mcbone.net 3,434 0.55
11 141.22.4.130=proxy.haw-hamburg.de 3,211 0.52
12 192.35.17.132=p1fsc.netz.sbs.de 3,110 0.50
13 194.138.37.43=proxy5.sbs.de 3,090 0.50
14 192.92.126.139=(not found) 3,063 0.49
15 66.130.142.152=modemcable152.142-130-66.que.mc.videotron.ca 2,962 0.48
16 62.104.220.91=sgt2-t6-2.mcbone.net 2,817 0.45
17 199.105.245.2=(not found) 2,791 0.45
18 80.135.216.214=p5087D8D6.dip.t-dialin.net 2,761 0.44
19 210.51.248.229=(not found) 2,731 0.44
209.247.55.133=dialup-209.247.55.133.Dial1.SanFrancisco1.Level3.
20 2,714 0.44
net
21 199.105.245.109=(not found) 2,576 0.41
22 217.0.120.105=pD9007869.dip.t-dialin.net 2,570 0.41
23 217.57.198.86=(not found) 2,569 0.41
24 199.105.244.164=(not found) 2,540 0.41
25 62.104.220.76=sgt2-t7-1.mcbone.net 2,518 0.40
Sum 622,757 100.00

To top of page

Top 25 of 526 IPs and host names of multiple visitors , sorted by number
of visists

N IPs and host names of multiple visitors visits %


1 209.73.162.20=trek13.sv.av.com 158 8.04
2 194.231.30.86=srv-ze-robot1.tricus.com 26 1.32
3 193.170.87.120=(not found) 19 0.97
4 193.170.124.123=(not found) 19 0.97
5 216.200.130.204=ezspider304.directhit.com 16 0.81
6 194.138.37.43=proxy5.sbs.de 14 0.71
7 24.12.71.33=ct515021-b.blmngtn1.in.home.com 14 0.71
8 194.109.6.96=tisnix.xs4all.nl 14 0.71
9 194.65.14.77=pr7-ts.telepac.pt 13 0.66
66.130.142.152=modemcable152.142-130-66.que.mc.videotron.
10 12 0.61
ca
11 129.116.190.238=dhcp-238.csr.utexas.edu 11 0.56
12 216.239.46.100=crawl4.googlebot.com 11 0.56
13 213.77.180.179=pa179.zgierz.sdi.tpnet.pl 10 0.51
14 24.102.64.130=CPE0050BA74853C.cpe.net.cable.rogers.com 10 0.51
15 212.186.17.55=chello212186017055.11.vie.surfer.at 10 0.51
16 213.97.246.214=213-97-246-214.uc.nombres.ttd.es 9 0.46
17 216.20.10.34=squidproxy2.mecnet.net 9 0.46
18 200.199.20.109=serrambi.telemar-pe.com.br 9 0.46
19 24.221.178.66=cpe-24-221-178-66.ca.sprintbbd.net 9 0.46
20 212.186.38.253=212186038253.12.vie.surfer.at 9 0.46
21 216.239.35.4=proxy.google.com 9 0.46
22 210.117.67.215=(not found) 9 0.46
23 210.117.67.223=(not found) 9 0.46
24 216.239.46.19=crawl1.googlebot.com 9 0.46
25 216.239.46.153=crawl6.googlebot.com 9 0.46
Sum 1,965 100.00

To top of page

Top 25 of 65 countries of origin , sorted by number of files

N countries of origin times %


1 net 11,723 30.75
2 (unresolved) 7,644 20.05
3 de 4,248 11.14
4 com 4,047 10.61
5 be 1,096 2.87
6 at 947 2.48
7 pt 742 1.95
8 ca 731 1.92
9 ch 659 1.73
10 pl 568 1.49
11 nl 498 1.31
12 se 438 1.15
13 mx 413 1.08
14 it 374 0.98
15 es 370 0.97
16 edu 359 0.94
17 au 357 0.94
18 br 203 0.53
19 fr 162 0.42
20 nz 151 0.40
21 su 150 0.39
22 sk 150 0.39
23 uk 145 0.38
24 gr 130 0.34
25 my 122 0.32
Sum 38,127 100.00

To top of page

Top 25 of 86 pathes , sorted by number of files

N pathes times %
1 /avr_gra/ 12,618 33.09
2 /avr_en/beginner/ 4,912 12.88
3 / 4,422 11.60
4 /avr_de/ 4,191 10.99
5 /avr_en/ 4,144 10.87
6 /avr_de/beginner/ 4,130 10.83
7 /avr_en/source/ 1,317 3.45
8 /avr_de/quellen/ 1,285 3.37
9 /avr_de/rechnen/ 478 1.25
10 /avr_en/calc/ 399 1.05
11 /spicons/ 75 0.20
12 /avr_en/source// 21 0.06
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
13 20AVR-Assemble 8 0.02
r-Dateien/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
14 %20la 6 0.02
nguage_files/
15 /rechnen/ 5 0.01
16 /avr_en/beginner/sram_files/ 4 0.01
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
17 %20la 4 0.01
nguage002_files/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
18 %20la 4 0.01
nguage_archivos/
19 http://www.avr-asm-tutorial.net/avr_de/ 4 0.01
20 http://www.avr-asm-tutorial.net/avr_gra/ 3 0.01
21 /avr_de/beginner/Rechnen-Dateien/ 3 0.01
22 /avr_de/beginner/Tabellen-Dateien/ 3 0.01
23 /avr_en/beginner/tools_files/ 2 0.01
24 /avr_en/beginner/registers_files/ 2 0.01
25 /avr_en/beginner/tables_files/ 2 0.01
Sum 38,127 100.00

To top of page

Top 25 of 86 pathes , sorted by kbytes

N pathes kbytes %
1 / 387,740 62.26
2 /avr_gra/ 78,827 12.66
3 /avr_en/beginner/ 40,820 6.55
4 /avr_de/beginner/ 34,795 5.59
5 /avr_de/ 24,581 3.95
6 /avr_en/ 22,418 3.60
7 /avr_de/rechnen/ 8,994 1.44
8 /avr_en/calc/ 8,627 1.39
9 /avr_de/quellen/ 7,716 1.24
10 /avr_en/source/ 7,619 1.22
11 /spicons/ 275 0.04
12 /avr_en/source// 40 0.01
13 http://www.avr-asm-tutorial.net/avr_gra/ 31 0.00
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
14 20AVR-Assemble 16 0.00
r-Dateien/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
15 %20la 12 0.00
nguage_files/
16 /rechnen/ 10 0.00
17 http://www.avr-asm-tutorial.net/avr_de/ 10 0.00
18 /avr_en/beginner/sram_files/ 8 0.00
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
19 %20la 8 0.00
nguage002_files/
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler
20 %20la 8 0.00
nguage_archivos/
21 /avr_de/beginner/../ 8 0.00
22 /avr_de/beginner/Rechnen-Dateien/ 6 0.00
23 /avr_de/beginner/Tabellen-Dateien/ 6 0.00
24 /avr_en/beginner/tools_files/ 4 0.00
25 /avr_en/beginner/registers_files/ 4 0.00
Sum 622,757 100.00

To top of page

Top 25 of 516 requested files , sorted by number of files

N requested files times %


1 /avr_gra/stk_lcd.jpg 2,413 6.33
2 /avr_gra/RingLogo.jpg 1,599 4.19
3 /avr_de/index.html 1,404 3.68
4 /avr_en/index.html 1,325 3.48
5 /avr_gra/2313.gif 1,188 3.12
6 /index.html 1,145 3.00
7 /avr_2313.gif 1,030 2.70
8 /avr_gra/screenshot.gif 1,019 2.67
9 /avr-asm-tutorial.gif 991 2.60
10 /avr_en/beginner/RIGHT.html 715 1.88
11 /avr_en/beginner/index.html 686 1.80
12 /avr_en/beginner/LEFT.html 665 1.74
13 /avr_de/beginner/rechts.html 605 1.59
14 /avr_de/beginner/index.html 578 1.52
15 /avr_de/beginner/links.html 574 1.51
16 /avr_en.zip 543 1.42
17 /avr_gra/apps.jpg 522 1.37
18 /avr_gra/AT90S8515.jpg 516 1.35
19 /avr_en/beginner/TOOLS.html 417 1.09
20 /avr_gra/stk200lcd.jpg 414 1.09
/avr_de/beginner/werkzeuge.
21 405 1.06
html
22 /avr_de/apps.html 354 0.93
23 /avr_gra/stk_ram.jpg 341 0.89
24 /avr_gra/sram.gif 312 0.82
25 /avr_de/avr_tut.html 288 0.76
Sum 38,127 100.00

To top of page

Top 25 of 516 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_en.zip 205,182 32.95
2 /avr_de.zip 156,356 25.11
3 /avr_2313.gif 16,686 2.68
4 /avr_de/index.html 7,599 1.22
5 /avr_gra/2313.gif 6,912 1.11
6 /avr_gra/stk_lcd.jpg 6,865 1.10
7 /avr_gra/AT90S8515.jpg 6,806 1.09
8 /avr_en/index.html 6,289 1.01
9 /avr_en/beginner/JUMP.html 5,924 0.95
10 /avr_de/beginner/sprung.html 4,929 0.79
11 /avr_de/dcf77uhr.html 4,644 0.75
12 /avr_gra/stu352.gif 4,125 0.66
13 /avr_gra/stk200lcd.jpg 4,114 0.66
14 /avr_de/beginner/rechnen.html 4,077 0.65
15 /avr_gra/isp.gif 3,925 0.63
16 /avr_de/beginner/werkzeuge.html 3,828 0.61
17 /avr_en/beginner/CALC.html 3,796 0.61
18 /avr_en/beginner/TOOLS.html 3,774 0.61
19 /avr_en/CLOCK.html 3,744 0.60
20 /avr_en/beginner/RIGHT.html 3,734 0.60
21 /avr_gra/stk_ram.jpg 3,669 0.59
22 /index.html 3,599 0.58
/avr_en/beginner/COMMANDS.
23 3,422 0.55
html
24 /avr_de/beginner/commands.html 3,344 0.54
25 /avr_gra/view.gif 3,330 0.53
Sum 622,757 100.00

To top of page

Top 25 of 349 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /avr_de/index.html 1,404 7.46
2 /avr_en/index.html 1,325 7.04
3 /index.html 1,145 6.09
4 /avr_en/beginner/RIGHT.html 715 3.80
5 /avr_en/beginner/index.html 686 3.65
6 /avr_en/beginner/LEFT.html 665 3.54
7 /avr_de/beginner/rechts.html 605 3.22
8 /avr_de/beginner/index.html 578 3.07
9 /avr_de/beginner/links.html 574 3.05
10 /avr_en/beginner/TOOLS.html 417 2.22
11 /avr_de/beginner/werkzeuge.html 405 2.15
12 /avr_de/apps.html 354 1.88
13 /avr_de/avr_tut.html 288 1.53
14 /avr_en/AVR_TUT.html 281 1.49
15 /avr_en/beginner/REGISTER.html 272 1.45
16 /avr_en/beginner/WHY.html 267 1.42
17 /avr_en/beginner/JUMP.html 261 1.39
/avr_en/beginner/STRUCTURE.
18 249 1.32
html
19 /avr_en/beginner/PORTS.html 243 1.29
20 /avr_en/APPS.html 232 1.23
21 /avr_de/beginner/register.html 213 1.13
22 /avr_de/beginner/Warum.html 204 1.08
23 /avr_de/avr_hard.html 204 1.08
24 /avr_de/beginner/commands.html 204 1.08
25 /avr_en/AVR_HARD.html 198 1.05
Sum 18,811 100.00

To top of page

Top 25 of 349 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 7,599 5.93
2 /avr_en/index.html 6,289 4.90
3 /avr_en/beginner/JUMP.html 5,924 4.62
4 /avr_de/beginner/sprung.html 4,929 3.84
5 /avr_de/dcf77uhr.html 4,644 3.62
6 /avr_de/beginner/rechnen.html 4,077 3.18
7 /avr_de/beginner/werkzeuge.html 3,828 2.99
8 /avr_en/beginner/CALC.html 3,796 2.96
9 /avr_en/beginner/TOOLS.html 3,774 2.94
10 /avr_en/CLOCK.html 3,744 2.92
11 /avr_en/beginner/RIGHT.html 3,734 2.91
12 /index.html 3,599 2.81
/avr_en/beginner/COMMANDS.
13 3,422 2.67
html
14 /avr_de/beginner/commands.html 3,344 2.61
15 /avr_de/beginner/rechts.html 3,098 2.42
16 /avr_en/beginner/PDETAIL.html 2,744 2.14
17 /avr_en/beginner/REGISTER.html 2,637 2.06
18 /avr_en/beginner/PORTS.html 2,549 1.99
19 /avr_de/beginner/pdetail.html 2,291 1.79
20 /avr_en/beginner/SRAM.html 2,273 1.77
21 /avr_de/beginner/ports.html 2,132 1.66
22 /avr_en/beginner/LEFT.html 2,028 1.58
23 /avr_de/beginner/portdetail.html 2,016 1.57
24 /avr_de/beginner/sram.html 1,809 1.41
25 /avr_de/beginner/register.html 1,750 1.36
Sum 128,226 100.00

To top of page

Top 15 of 15 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/stk_lcd.jpg 2,413 34.99
2 /avr_gra/RingLogo.jpg 1,599 23.18
3 /avr_gra/apps.jpg 522 7.57
4 /avr_gra/AT90S8515.jpg 516 7.48
5 /avr_gra/stk200lcd.jpg 414 6.00
6 /avr_gra/stk_ram.jpg 341 4.94
7 /avr_gra/stk200.jpg 274 3.97
8 /avr_gra/remote.jpg 191 2.77
9 /avr_gra/sio_conn.jpg 181 2.62
10 /avr_gra/lcd_conn.jpg 148 2.15
11 /avr_gra/lcd_board.jpg 147 2.13
12 /avr_gra/pwg.jpg 131 1.90
13 /spicons/notfound.jpg 18 0.26
14 http://www.avr-asm-tutorial.net/avr_gra/stk200.jpg 1 0.01
http://www.avr-asm-tutorial.net/avr_gra/stk_ram.
15 1 0.01
jpg
Sum 6,897 100.00

To top of page

Top 25 of 68 GIF-files , sorted by number of files

N GIF-files times %
1 /avr_gra/2313.gif 1,188 14.68
2 /avr_2313.gif 1,030 12.72
/avr_gra/screenshot.
3 1,019 12.59
gif
4 /avr-asm-tutorial.gif 991 12.24
5 /avr_gra/sram.gif 312 3.85
/avr_gra/pcm2pwg4.
6 193 2.38
gif
7 /avr_gra/wavrasm.gif 190 2.35
8 /avr_gra/isp.gif 177 2.19
9 /avr_gra/assemble.gif 156 1.93
10 /avr_gra/ROL.gif 142 1.75
11 /avr_gra/ROR.gif 142 1.75
12 /avr_gra/studio.gif 138 1.70
13 /avr_gra/eingabe.gif 128 1.58
14 /avr_gra/silliksaar.gif 120 1.48
15 /avr_gra/options.gif 110 1.36
16 /avr_gra/hex.gif 106 1.31
17 /avr_gra/view.gif 99 1.22
18 /avr_gra/clock.gif 95 1.17
19 /avr_gra/step1.gif 92 1.14
20 /avr_gra/obj.gif 87 1.07
21 /avr_gra/newproj.gif 85 1.05
22 /avr_gra/step6.gif 85 1.05
23 /avr_gra/lst.gif 83 1.03
24 /avr_gra/stu352.gif 78 0.96
25 /avr_gra/sim1.gif 78 0.96
Sum 8,095 100.00

To top of page

Top 25 of 92 entry pages , sorted by number of files

N entry pages times %


1 /avr_de/index.html 534 19.76
2 /avr_en/index.html 512 18.95
3 /index.html 432 15.99
4 /avr_de/beginner/werkzeuge.html 83 3.07
5 /avr_de/beginner/index.html 75 2.78
6 /avr_en/beginner/TOOLS.html 64 2.37
7 /avr_en/TESTLCD.html 44 1.63
8 /avr_de/beginner/Warum.html 43 1.59
9 /avr_en/beginner/index.html 39 1.44
10 /avr_en/beginner/STUDIO352.html 38 1.41
11 /avr_de/beginner/rechnen.html 36 1.33
12 /avr_en/beginner/RIGHT.html 33 1.22
13 /avr_de/beginner/struktur.html 30 1.11
14 /avr_de/apps.html 29 1.07
15 /avr_de/dcf77uhr.html 29 1.07
16 /avr_de/beginner/studio352.html 29 1.07
17 /avr_de/remote.html 29 1.07
18 /avr_de/testram.html 27 1.00
/avr_en/beginner/STRUCTURE.
19 25 0.93
html
20 /avr_en/CLOCK.html 24 0.89
21 /avr_en/REMOTE.html 22 0.81
22 /avr_de/avr_tut.html 22 0.81
23 /avr_de/beginner/rechts.html 21 0.78
24 /avr_de/beginner/sprung.html 18 0.67
25 /avr_de/pwg.html 18 0.67
Sum 2,702 100.00

To top of page

Top 25 of 110 cheat pages , sorted by number of files

N cheat pages times %


1 /avr_de/index.html 364 12.53
2 /index.html 327 11.25
3 /avr_en/index.html 275 9.46
4 /avr_de/beginner/werkzeuge.html 114 3.92
5 /avr_en/beginner/TOOLS.html 90 3.10
6 /avr_de/apps.html 71 2.44
7 /avr_de/beginner/rechts.html 52 1.79
8 /avr_en/beginner/RIGHT.html 51 1.75
9 /avr_de/beginner/rechnen.html 51 1.75
10 /avr_en/beginner/STUDIO352.html 42 1.45
11 /avr_en/beginner/JUMP.html 42 1.45
12 /avr_de/beginner/Warum.html 42 1.45
13 /avr_en/APPS.html 41 1.41
14 /avr_de/remote.html 41 1.41
15 /avr_en/TESTLCD.html 41 1.41
16 /avr_de/dcf77uhr.html 41 1.41
17 /avr_de/beginner/struktur.html 40 1.38
18 /avr_de/beginner/studio352.html 39 1.34
19 /avr_de/avr_tut.html 38 1.31
/avr_en/beginner/STRUCTURE.
20 37 1.27
html
21 /avr_de/avr_hard.html 36 1.24
22 /avr_en/beginner/CALC.html 31 1.07
23 /avr_en/CLOCK.html 30 1.03
24 /avr_en/AVR_HARD.html 30 1.03
25 /avr_en/beginner/REGISTER.html 29 1.00
Sum 2,906 100.00

To top of page

Top 25 of 110 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_en/index.html 1,729 14.18
2 /avr_de/index.html 1,722 14.13
3 /avr_en/beginner/index.html 1,189 9.75
4 /avr_de/beginner/index.html 963 7.90
5 /avr_en/beginner/RIGHT.html 940 7.71
6 /avr_en/beginner/LEFT.html 764 6.27
7 /avr_de/beginner/links.html 741 6.08
8 /avr_de/beginner/rechts.html 481 3.95
9 / 457 3.75
10 /avr_de/avr_tut.html 270 2.21
11 /avr_en/AVR_TUT.html 240 1.97
12 /avr_de/ 217 1.78
13 /avr_de/apps.html 207 1.70
14 /avr_en/AVR_HARD.html 169 1.39
15 /avr_de/avr_hard.html 156 1.28
16 /avr_en/APPS.html 155 1.27
17 /avr_de/avr_soft.html 154 1.26
18 /avr_en/AVR_SOFT.html 149 1.22
19 /index.html 136 1.12
20 /avr_de/beginner/commands.html 116 0.95
/avr_en/beginner/STRUCTURE.
21 105 0.86
html
22 /avr_de/beginner/ports.html 87 0.71
23 /avr_de/beginner/struktur.html 82 0.67
/avr_en/beginner/COMMANDS.
24 66 0.54
html
25 /avr_en/beginner/PORTS.html 64 0.53
Sum 12,190 100.00

To top of page

Top 25 of 179 external referrers , sorted by number of files

N external referrers times %


1 - 4,595 71.77
2 http://r.webring.com/hub?ring=avr&list 255 3.98
3 http://www.dg4fac.de/avr/avr_en/index.html 208 3.25
4 http://www.dg4fac.de/avr/avr_de/ 130 2.03
5 http://www.dg4fac.de/avr/avr_en/ 120 1.87
6 http://www.dg4fac.de/avr/avr_de/index.html 77 1.20
7 http://www.mikrocontroller.net/links.htm 52 0.81
8 http://www.iptel-now.de/HOWTO/ATMEL/atmel.html 39 0.61
http://www.dg4fac.de/avr/avr_de/beginner/werkzeuge.
9 37 0.58
html
10 http://www.dg4fac.de/avr/avr_en/beginner/TOOLS.html 35 0.55
11 http://R.webring.com/hub?ring=avr&list 31 0.48
12 http://www.dg4fac.de/avr/ 26 0.41
13 http://www.lug-kiel.de/links/micros.html 25 0.39
14 http://www.dg4fac.de/rechtsunten.html 24 0.37
15 http://www.dg4fac.de/avr/avr_en/TESTLCD.html 23 0.36
16 http://www.dg4fac.de/avr/avr_de/beginner/index.html 20 0.31
17 http://www.dg4fac.de/linksunten.html 20 0.31
18 [unknown origin] 19 0.30
19 http://www.ask.com/ 19 0.30
20 http://www.dg4fac.de/avr/avr_de/dcf77uhr.html 18 0.28
21 http://www.dg4fac.de/avr/avr_en/beginner/RIGHT.html 18 0.28
22 http://www.dg4fac.de/avr/avr_en/CLOCK.html 17 0.27
23 http://www.dg4fac.de/avr/avr_en/beginner/index.html 16 0.25
24 http://www.dg4fac.de/avr/avr_de/beginner/Warum.html 15 0.23
25 http://www.dg4fac.de/avr/avr_tut.html 15 0.23
Sum 6,402 100.00

To top of page

Top 16 of 16 search engines , sorted by number of files

N search engines times %


1 http://www.google.com 84 38.36
2 http://de.search.yahoo.com 68 31.05
3 http://www.google.de 35 15.98
4 http://google.yahoo.com 7 3.20
5 http://de.google.yahoo.com 6 2.74
6 http://www.caloweb.de 5 2.28
7 http://suchen.com 4 1.83
8 http://www.google.nl 2 0.91
http://www.wavysound.
9 1 0.46
com
10 http://ask.com 1 0.46
11 http://kr.search.yahoo.com 1 0.46
12 http://suche.freenet.de 1 0.46
13 http://images.google.com 1 0.46
14 http://216.15.219.40 1 0.46
15 http://www.google.ca 1 0.46
http://www.netmadeira.
16 1 0.46
com
Sum 219 100.00

To top of page

Top 25 of 134 search strings , sorted by number of files

N search strings times %


1 atmel 18 8.22
2 avr 18 8.22
3 AVR 11 5.02
4 at89c51 8 3.65
5 avr tutorial 5 2.28
6 atmel purplr card 4 1.83
7 assembler 4 1.83
8 atmel tutorial 4 1.83
9 ATMEL 3 1.37
10 Assembler lernen 3 1.37
11 atmel avr lcd asm 3 1.37
12 asm atmel 2 0.91
13 avr compiler 2 0.91
14 introduction to AVR Assembler programming 2 0.91
15 avr tabelle 2 0.91
16 tan silliksaar 2 0.91
17 assembly programing 2 0.91
18 zähler atmel 2 0.91
19 Assembler Menue 2 0.91
cache:DSXAQoUKdAA:www.avr-asm-tutorial.net/avr_de/apps.html
20 rechteckge 2 0.91
nerator schaltplan
21 parity calculation uart avr 2 0.91
22 Tan Silliksaar AVR 2 0.91
23 assembler tutorial 2 0.91
24 at90s2313 + timer 2 0.91
25 atmel avr dcf77 2 0.91
Sum 219 100.00

To top of page

Top 8 of 8 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 31,554 82.76
2 304 Not changed 5,417 14.21
3 206 Partial information 658 1.73
4 404 File not found 243 0.64
5 301 Permanently moved 116 0.30
6 300 ? 80 0.21
7 403 Forbidden 51 0.13
8 xxx Unknown error 8 0.02
Sum 38,127 100.00

To top of page

Top 25 of 118 files not found , sorted by number of files

N files not found times %


1 /avr_de/beginner/www.atmel.com 50 20.58
2 /avr_en/beginner/www.atmel.com 32 13.17
3 /robots.txt 9 3.70
4 /avr_en/beginner/favicon.ico 8 3.29
5 /avr_de/beginner/favicon.ico 5 2.06
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
6 20AVR-Assemble 5 2.06
r-Dateien/links.htm

http://www.avr-asm-tutorial.net/weblox_en/2001y.html (1 of 2)1/20/2009 8:06:23 PM


Weblog statistic for http://www.avr-asm-tutorial.net

7 /rechnen/index.html 5 2.06
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
8 20la 4 1.65
nguage_files/LEFT.htm
9 /_vti_inf.html 4 1.65
10 /favicon.ico 3 1.23
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
11 20la 2 0.82
nguage_files/RIGHT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
12 20la 2 0.82
nguage002_files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
13 20la 2 0.82
nguage002_files/WHY.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
14 20la 2 0.82
nguage_archivos/LEFT.htm
15 /avr_de/beginner/Rechnen-Dateien/links.htm 2 0.82
16 /avr_de/beginner/Tabellen-Dateien/links.htm 2 0.82
17 /avr_gra/ROL.gif 2 0.82
18 /avr_gra/ROR.gif 2 0.82
19 /avr_de/test.lst 2 0.82
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
20 20la 2 0.82
nguage3_files/LEFT.htm
21 /avr_en/beginner/why_files/LEFT.htm 1 0.41
22 /avr_en/beginner/tools_files/LEFT.htm 1 0.41
23 /avr_en/beginner/tools_files/TOOLS.htm 1 0.41
24 /avr_en/beginner/registers_files/LEFT.htm 1 0.41
25 /avr_en/beginner/registers_files/REGISTER.htm 1 0.41
Sum 243 100.00

To top of page

Top 25 of 92 browser types , sorted by number of files

N browser types times %


1 Mozilla/4.0 26,711 70.06
2 Mozilla/4.7 1,210 3.17
3 Mozilla/4.5 1,068 2.80
4 Mozilla/3.0 935 2.45
5 Mozilla/5.0 855 2.24
6 WebZIP/4.0 553 1.45
7 Mozilla/4.77 534 1.40
8 - 486 1.27
9 Teleport Pro/1.29 426 1.12
10 eCatch/3.0 362 0.95
11 Mozilla/4.76 310 0.81
12 Mozilla/4.75 307 0.81
FAST-
13 296 0.78
WebCrawler/3.3
14 Scooter-W3.1.2 277 0.73
15 Mozilla/4.73 258 0.68
16 WebZIP/4.1 226 0.59
17 Mozilla/4.78 215 0.56
18 Teleport 204 0.54
19 Googlebot/2.1 201 0.53
20 Wget/1.5.3 185 0.49
21 Mozilla/3.01 179 0.47
22 WebReaper 179 0.47
23 Mozilla/4.74 151 0.40
24 Mozilla/4.61 151 0.40
25 Mozilla/4.72 142 0.37
Sum 38,127 100.00

To top of page

Top 25 of 90 browser versions , sorted by number of files

N browser versions times %


1 MSIE 5.5 8,252 21.64
2 MSIE 6.0 7,170 18.81
3 unknown 6,558 17.20
4 MSIE 5.0 5,291 13.88
5 MSIE 5.01 4,459 11.70
6 Macintosh 1,323 3.47
7 MSIE 4.01 790 2.07
8 HTTrack 3.0x 537 1.41
9 Pro/1.29 426 1.12
10 WebCapture 2.0 332 0.87
11 HTTrack 2.0x 245 0.64
12 MSIE 6.0b 240 0.63
13 C-CCK-MCD DT 227 0.60
14 Pro/1.29.1590 204 0.54
15 MSIE 5.00 164 0.43
16 AOL 5.0 149 0.39
17 Netscape6/6.1 122 0.32
18 Konqueror/2.2.1 117 0.31
19 Pro/1.28 104 0.27
20 Opera/5.12 85 0.22
21 Pro/1.23 81 0.21
22 sun4u 79 0.21
C-CCK-MCD {C-
23 74 0.19
UDP
24 Netscape6/6.2 66 0.17
25 Libro Online 59 0.15
Sum 38,127 100.00

To top of page

Top 25 of 63 operating systems , sorted by number of files

N operating systems times %


1 Windows 98 15,725 41.24
2 Windows NT 5.0 6,076 15.94
3 unknown 5,159 13.53
4 Windows NT 5.1 2,255 5.91
5 Macintosh 1,397 3.66
6 Windows NT 4.0 1,216 3.19
7 Windows NT 1,122 2.94
8 Windows 95 1,113 2.92
9 WinNT 852 2.23
10 Win98 838 2.20
11 Windows 566 1.48
12 Win95 399 1.05
13 Linux i686 234 0.61
14 Windows 2000 108 0.28
15 Linux 101 0.26
Linux 2.4.3-20mdk
16 79 0.21
i686
17 Windows ME 75 0.20
18 Linux 2.4.6 i686 62 0.16
19 Linux 2.4.10-4GB 58 0.15
20 SunOS 5.6 sun4u 54 0.14
21 X11 48 0.13
22 Linux 2.4.5 i686 48 0.13
23 Linux 2.4.17 i686 48 0.13
24 CP/M 42 0.11
25 Linux 2.2.12 i386 39 0.10
Sum 38,127 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,344 6.15
2 01 1,700 4.46
3 02 983 2.58
4 03 637 1.67
5 04 577 1.51
6 05 448 1.18
7 06 554 1.45
8 07 469 1.23
9 08 960 2.52
10 09 1,441 3.78
11 10 1,729 4.53
12 11 1,683 4.41
13 12 1,737 4.56
14 13 2,151 5.64
15 14 2,177 5.71
16 15 1,935 5.08
17 16 2,423 6.36
18 17 1,974 5.18
19 18 1,984 5.20
20 19 2,137 5.60
21 20 1,726 4.53
22 21 1,771 4.65
23 22 2,525 6.62
24 23 2,062 5.41
Sum 38,127 100.00

To top of page

Created with Weblox, version 0.8, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2001y.html (2 of 2)1/20/2009 8:06:23 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Monthly sorted index ==> Log 2008m12

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , month 12

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 21477 IPs and host names , sorted by number of files

N IPs and host names times %


1 91.205.124.9=(not found) 2,504 0.64
2 85.178.210.56=e178210056.adsl.alicedsl.de 1,485 0.38
3 89.61.218.40=Zda28.z.pppool.de 1,161 0.30
4 67.195.37.157=llf320058.crawl.yahoo.net 1,096 0.28
5 66.249.71.206=crawl-66-249-71-206.googlebot.com 882 0.23
6 66.249.71.205=crawl-66-249-71-205.googlebot.com 873 0.22
7 66.249.71.207=crawl-66-249-71-207.googlebot.com 861 0.22
8 141.31.185.49=ip-141-31-185-49.nat.selfnet.de 827 0.21
9 125.163.229.71=71.subnet125-163-229.speedy.telkom.net.id 810 0.21
10 93.158.148.31=spider11.yandex.ru 799 0.21
11 91.37.247.13=p5B25F70D.dip.t-dialin.net 781 0.20
12 91.191.10.139=(not found) 754 0.19
13 128.119.91.226=culloden.ecs.umass.edu 752 0.19
14 62.218.64.137=simmu1-64-137.utaonline.at 751 0.19
125.163.229.120=120.subnet125-163-229.speedy.telkom.net.
15 611 0.16
id
16 84.168.114.83=p54A87253.dip.t-dialin.net 610 0.16
17 67.195.37.116=llf320025.crawl.yahoo.net 596 0.15
18 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 559 0.14
19 208.111.154.16=crawl2.nat.svl.searchme.com 511 0.13
20 65.55.212.136=(not found) 485 0.12
21 93.146.64.226=net-93-146-64-226.t2.dsl.vodafone.it 474 0.12
22 85.196.177.200=cm-200-177-vr.m-real.net 449 0.12
23 210.173.180.155=(not found) 445 0.11
24 92.105.57.123=123-57.105-92.cust.bluewin.ch 440 0.11
25 91.96.223.131=host-091-096-223-131.ewe-ip-backbone.de 407 0.10
Sum 389,361 100.00

To top of page

Top 25 of 21477 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.205.124.9=(not found) 75,079 1.77
2 85.178.210.56=e178210056.adsl.alicedsl.de 38,494 0.91
3 77.22.115.197=(not found) 32,553 0.77
4 91.191.10.139=(not found) 29,015 0.69
5 62.218.64.137=simmu1-64-137.utaonline.at 29,006 0.69
6 91.37.247.13=p5B25F70D.dip.t-dialin.net 28,966 0.68
7 84.168.114.83=p54A87253.dip.t-dialin.net 26,755 0.63
8 79.217.210.140=p4FD9D28C.dip.t-dialin.net 22,367 0.53
9 67.195.37.157=llf320058.crawl.yahoo.net 17,913 0.42
10 77.178.177.72=dtmd-4db2b148.pool.einsundeins.de 17,225 0.41
11 125.163.229.71=71.subnet125-163-229.speedy.telkom.net.id 16,957 0.40
12 93.146.64.226=net-93-146-64-226.t2.dsl.vodafone.it 16,588 0.39
13 65.55.212.136=(not found) 16,518 0.39
125.163.229.120=120.subnet125-163-229.speedy.telkom.net.
14 16,352 0.39
id
15 84.61.88.54=dslb-084-061-088-054.pools.arcor-ip.net 13,602 0.32
16 80.140.123.124=p508C7B7C.dip.t-dialin.net 11,348 0.27
17 77.20.16.74=(not found) 11,000 0.26
18 85.178.152.20=e178152020.adsl.alicedsl.de 10,927 0.26
19 194.147.209.5=proxy.rega.ch 10,529 0.25
20 80.120.130.73=(not found) 9,966 0.24
21 94.222.120.43=(not found) 9,335 0.22
22 89.53.117.221=Q75dd.q.strato-dslnet.de 8,682 0.21
23 93.158.148.31=spider11.yandex.ru 8,282 0.20
24 84.119.14.77=84-119-14-77.dynamic.xdsl-line.inode.at 8,244 0.19
25 66.249.71.207=crawl-66-249-71-207.googlebot.com 8,124 0.19
Sum 4,234,362 100.00

To top of page

Top 25 of 3823 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.205=crawl-66-249-71-205.googlebot.com 349 2.00
2 66.249.71.207=crawl-66-249-71-207.googlebot.com 344 1.97
3 66.249.71.206=crawl-66-249-71-206.googlebot.com 320 1.83
4 193.47.80.44=crawl8.exabot.com 208 1.19
5 67.195.37.157=llf320058.crawl.yahoo.net 183 1.05
6 208.111.154.16=crawl2.nat.svl.searchme.com 173 0.99
7 208.111.154.15=crawl1.nat.svl.searchme.com 153 0.88
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 141 0.81
9 67.195.37.116=llf320025.crawl.yahoo.net 140 0.80
10 81.52.143.16=natcrawlbloc03.net.m1.fti.net 138 0.79
11 81.52.143.15=natcrawlbloc01.net.m1.fti.net 123 0.70
12 81.52.143.26=natcrawlbloc05.net.m1.fti.net 118 0.68
13 88.131.106.16=(not found) 108 0.62
14 66.235.124.3=crawler5003.ask.com 91 0.52
15 67.195.37.111=llf320022.crawl.yahoo.net 90 0.51
16 65.55.212.136=(not found) 83 0.47
17 77.22.18.102=(not found) 78 0.45
18 193.252.149.16=natcrawlbloc04.net.s1.fti.net 69 0.39
19 58.239.73.120=(not found) 66 0.38
20 208.115.111.244=crawl3.dotnetdotcom.org 61 0.35
21 72.30.161.225=llf531025.crawl.yahoo.net 55 0.31
22 72.30.81.182=llf531210.crawl.yahoo.net 53 0.30
23 208.44.234.50=(not found) 52 0.30
65.55.209.158=msnbot-65-55-209-158.search.msn.
24 52 0.30
com
25 38.99.13.125=crawl-4.cuill.com 50 0.29
Sum 17,480 100.00

To top of page

Top 25 of 132 countries of origin , sorted by number of files

N countries of origin times %


1 net 117,564 30.19
2 Germany 84,178 21.62
3 (unresolved) 66,762 17.15
4 com 26,833 6.89
5 Austria 9,801 2.52
6 Poland 9,293 2.39
7 Switzerland 5,831 1.50
8 Netherlands 5,401 1.39
9 Italy 4,705 1.21
10 Indonesia 3,653 0.94
11 Hungary 3,519 0.90
12 India 3,387 0.87
13 edu 2,787 0.72
14 Belgium 2,741 0.70
15 Czech Republic 2,616 0.67
16 Mexico 2,357 0.61
17 Greece 2,150 0.55
18 Russian Federation 2,090 0.54
19 Lithuania 1,969 0.51
20 Romania 1,919 0.49
21 Canada 1,807 0.46
22 Sweden 1,775 0.46
23 United Kingdom 1,773 0.46
24 Finland 1,613 0.41
25 Brazil 1,604 0.41
Sum 389,361 100.00

To top of page

Top 25 of 250 pathes , sorted by number of files

N pathes times %
1 /common/ 138,408 35.55
2 /avr_gra/ 65,300 16.77
3 / 46,053 11.83
4 /avr_en/beginner/ 16,321 4.19
5 /avr_de/beginner/ 12,263 3.15
6 /avr_de/ 11,772 3.02
7 /avr_en/ 11,589 2.98
8 /avr_en/calc/ 7,194 1.85
9 /avr_de/rechnen/ 7,121 1.83
10 /avr_de/fcount/ 5,854 1.50
11 /avr_de/stepper/ 5,433 1.40
12 /avr_en/source/ 4,739 1.22
13 /avr_de/praesentation/ 4,665 1.20
14 /avr_de/quellen/ 4,066 1.04
15 /avr_en/keypad/ 3,769 0.97
16 /avr_en/stepper/ 3,017 0.77
/avr_de/rechteckgen/
17 2,934 0.75
bilder/
18 /avr_de/keypad/ 2,873 0.74
19 /gavrasm/ 2,812 0.72
20 /avr_en/signalgen/pics/ 2,750 0.71
21 /avr_de/zeitschleifen/ 2,689 0.69
22 /avr_de/interrupts/ 2,087 0.54
23 /akkuload/ 1,535 0.39
24 /privat/magloop/ 1,482 0.38
25 /avr_en/signalgen/ 1,183 0.30
Sum 389,361 100.00

To top of page

Top 25 of 250 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 800,721 18.91
2 /avr_gra/ 509,348 12.03
3 /avr_de/intro/pdf/ 421,366 9.95
4 / 257,135 6.07
5 /avr_de/fcount/ 220,804 5.21
6 /avr_de/ 183,081 4.32
7 /avr_en/ 163,887 3.87
8 /avr_de/stepper/ 144,191 3.41
9 /avr_en/beginner/ 138,791 3.28
10 /avr_de/beginner/ 114,580 2.71
/avr_de/rechteckgen/
11 76,442 1.81
bilder/
12 /avr_en/stepper/ 76,378 1.80
13 /avr_en/signalgen/pics/ 73,209 1.73
14 /privat/magloop/ 70,381 1.66
15 /common/ 66,389 1.57
16 /avr_en/calc/ 64,962 1.53
17 /avr_de/rechnen/ 63,530 1.50
18 /gavrasm/v21/ 57,260 1.35
19 /avr_de/intro/ppt/ 56,317 1.33
20 /avr_en/signalgen/ 53,780 1.27
21 /avr_de/rechteckgen/ 49,087 1.16
22 /weblox_de/ 47,384 1.12
23 /weblox_en/ 41,792 0.99
24 /gavrasm/v22/ 41,329 0.98
25 /akkuload/ 37,599 0.89
Sum 4,234,362 100.00

To top of page

Top 25 of 2186 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 20,509 5.27
2 /avr_gra/RingLogo.jpg 10,823 2.78
3 /common/app.gif 8,983 2.31
4 /common/akkuload.gif 8,982 2.31
/common/knowhow.
5 8,979 2.31
gif
/common/download.
6 8,965 2.30
gif
7 /common/clock.gif 8,920 2.29
8 /common/adc.gif 8,904 2.29
9 /common/keyb.gif 8,904 2.29
10 /common/gavrasm.gif 8,902 2.29
11 /avr_gra/stk_lcd.jpg 8,900 2.29
12 /common/example.gif 8,897 2.29
/common/gavrasmw.
13 8,897 2.29
gif
14 /common/r2r.gif 8,895 2.28
15 /common/beginner.gif 8,894 2.28
16 /common/calc.gif 8,878 2.28
17 /common/hardware.gif 8,872 2.28
18 /index.html 6,272 1.61
19 /avr_en/index.html 5,361 1.38
20 /avr_de/index.html 5,057 1.30
21 /avr_2313.gif 4,864 1.25
22 /dg4fac.gif 4,788 1.23
23 /avr-asm-tutorial.gif 4,778 1.23
24 /common/ints.gif 4,517 1.16
25 /common/delay.gif 4,516 1.16
Sum 389,361 100.00

To top of page

Top 25 of 2186 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 255,610 6.04
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 158,825 3.75
3 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 156,941 3.71
/avr_de/praesentation/Teil_5b_Beispiel01_02.
4 114,733 2.71
pdf
5 /avr_de/index.html 114,177 2.70
6 /avr_en/index.html 110,940 2.62
7 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 103,843 2.45
8 /avr_2313.gif 85,606 2.02
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 82,611 1.95
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 66,152 1.56
11 /dg4fac.gif 51,156 1.21
12 /avr_gra/pwm_simul.jpg 47,136 1.11
13 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 44,369 1.05
14 /avr_de/fcount/dscf0004.jpg 43,473 1.03
15 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 43,310 1.02
16 /avr_gra/r2r_hardware.jpg 40,566 0.96
17 /favicon.ico 40,383 0.95
18 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 40,221 0.95
19 /avr_de/fcount/dscf0005.jpg 37,745 0.89
20 /avr_de/stepper/stepper_v1.gif 35,647 0.84
21 /avr_de/fcount/dscf0001.jpg 35,549 0.84
22 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 35,192 0.83
23 /avr_de/intro/pdf/Teil1_Prozessor.pdf 34,843 0.82
24 /avr_en/signalgen/pics/rectgen_wiring.jpg 33,613 0.79
25 /index.html 33,144 0.78
Sum 4,234,362 100.00

To top of page

Top 25 of 667 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 6,272 7.53
2 /avr_en/index.html 5,361 6.44
3 /avr_de/index.html 5,057 6.07
4 /avr_en/beginner/index.html 2,882 3.46
5 /avr_en/beginner/RIGHT.html 2,775 3.33
6 /avr_en/beginner/LEFT.html 2,772 3.33
7 /avr_de/beginner/index.html 1,896 2.28
8 /avr_de/beginner/links.html 1,830 2.20
9 /avr_de/beginner/rechts.html 1,812 2.18
/avr_en/beginner/HARDWARE.
10 1,067 1.28
html
11 /avr_en/beginner/REGISTER.html 957 1.15
12 /avr_en/beginner/JUMP.html 807 0.97
13 /avr_en/keypad/keyboard.html 805 0.97
14 /avr_de/beginner/hardware.html 773 0.93
15 /avr_de/stepper/stepper.html 755 0.91
16 /avr_en/AVR_DAC.html 747 0.90
17 /avr_de/praesentation/index.html 705 0.85
18 /avr_de/beginner/register.html 693 0.83
19 /avr_de/beginner/sprung.html 659 0.79
20 /avr_en/beginner/TOOLS.html 658 0.79
21 /avr_en/beginner/PORTS.html 652 0.78
22 /avr_de/apps.html 641 0.77
23 /avr_en/beginner/SRAM.html 624 0.75
24 /avr_de/keypad/keyboard.html 620 0.74
25 /avr_de/beginner/werkzeuge.html 598 0.72
Sum 83,295 100.00

To top of page

Top 25 of 667 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 114,177 11.69
2 /avr_en/index.html 110,940 11.36
3 /index.html 33,144 3.39
4 /avr_en/beginner/RIGHT.html 20,040 2.05
5 /avr_en/beginner/JUMP.html 19,176 1.96
6 /avr_de/beginner/sprung.html 17,933 1.84
7 /avr_de/dcf77uhr.html 17,396 1.78
8 /gb_new.html 16,457 1.68
9 /avr_en/keypad/keyboard.html 16,451 1.68
10 /avr_en/beginner/CALC.html 14,171 1.45
11 /avr_en/beginner/LEFT.html 12,760 1.31
12 /avr_de/beginner/rechts.html 12,640 1.29
13 /avr_de/keypad/keyboard.html 12,548 1.28
14 /avr_de/beginner/rechnen.html 12,042 1.23
15 /avr_en/beginner/REGISTER.html 11,325 1.16
16 /avr_de/stepper/stepper.html 11,232 1.15
17 /avr_en/AVR_DAC.html 10,780 1.10
/avr_en/beginner/COMMANDS.
18 10,293 1.05
html
/avr_de/rechteckgen/rectgen_m8.
19 10,120 1.04
html
20 /avr_en/beginner/PDETAIL.html 9,697 0.99
21 /avr_de/beginner/pdetail.html 9,679 0.99
22 /avr_de/beginner/commands.html 9,571 0.98
23 /avr_de/avr_dac.html 9,518 0.97
24 /sitemap_de.html 9,477 0.97
25 /avr_en/signalgen/rectgen_m8.html 9,096 0.93
Sum 976,962 100.00

To top of page

Top 25 of 691 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 10,816 19.10
2 /avr_gra/stk_lcd.jpg 8,900 15.72
3 /avr_gra/8515.jpg 2,038 3.60
4 /avr_gra/avr_isp.jpg 1,673 2.95
5 /avr_gra/exp_2313.jpg 1,655 2.92
6 /avr_gra/exp2313g.jpg 1,655 2.92
7 /avr_gra/r2r_wave.jpg 1,314 2.32
8 /avr_gra/r2r_sawtooth.jpg 1,217 2.15
9 /avr_gra/r2r_triangle.jpg 1,154 2.04
10 /avr_gra/r2r_hardware.jpg 1,154 2.04
11 /avr_gra/r2r_sawtoothupperbound.jpg 1,146 2.02
12 /avr_gra/r2r_sawtooth741.jpg 1,144 2.02
13 /avr_gra/r2r_upperbound.jpg 1,140 2.01
14 /avr_gra/AT90S8515.jpg 1,035 1.83
15 /avr_gra/apps.jpg 865 1.53
16 /avr_gra/pwm_simul.jpg 846 1.49
17 /avr_gra/adc8conn.jpg 842 1.49
18 /avr_de/stepper/stepper_sm.jpg 768 1.36
19 /akkuload/dscf0030s.jpg 730 1.29
20 /avr_de/stepper/kp4m4-001.jpg 726 1.28
21 /avr_de/stepper/supply.jpg 724 1.28
22 /avr_de/stepper/driver.jpg 710 1.25
23 /avr_de/praesentation/zuendtester.jpg 635 1.12
/avr_de/rechteckgen/bilder/rectgen_280.
24 616 1.09
jpg
25 /avr_en/signalgen/pics/rectgen_280.jpg 597 1.05
Sum 56,632 100.00

To top of page

Top 25 of 437 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 8,980 4.35
2 /common/akkuload.gif 8,979 4.35
/common/knowhow.
3 8,976 4.35
gif
/common/download.
4 8,962 4.34
gif
5 /common/clock.gif 8,917 4.32
6 /common/adc.gif 8,901 4.31
7 /common/keyb.gif 8,901 4.31
8 /common/gavrasm.gif 8,899 4.31
9 /common/example.gif 8,894 4.31
/common/gavrasmw.
10 8,894 4.31
gif
11 /common/r2r.gif 8,892 4.31
12 /common/beginner.gif 8,891 4.31
13 /common/calc.gif 8,875 4.30
14 /common/hardware.gif 8,869 4.30
15 /avr_2313.gif 4,863 2.36
16 /dg4fac.gif 4,788 2.32
17 /avr-asm-tutorial.gif 4,778 2.32
18 /common/ints.gif 4,514 2.19
19 /common/delay.gif 4,513 2.19
20 /common/tn13.gif 4,498 2.18
21 /avr_gra/2313.gif 4,396 2.13
22 /avr_gra/exp2313.gif 1,737 0.84
23 /avr_gra/avr_isp.gif 1,675 0.81
24 /avr_gra/isp10pin.gif 1,661 0.81
25 /avr_gra/isp6pin.gif 1,657 0.80
Sum 206,291 100.00

To top of page

Top 25 of 218 entry pages , sorted by number of files

N entry pages times %


1 /index.html 2,814 16.89
2 /avr_en/index.html 1,832 10.99
3 /avr_de/index.html 1,552 9.31
4 /avr_en/beginner/index.html 815 4.89
5 /avr_de/beginner/index.html 472 2.83
6 /avr_en/AVR_DAC.html 412 2.47
7 /avr_de/stepper/stepper.html 411 2.47
8 /avr_de/fcount/fcount_m8.html 306 1.84
9 /avr_de/avr_dac.html 289 1.73
10 /avr_en/beginner/HARDWARE.html 278 1.67
11 /avr_en/keypad/keyboard.html 263 1.58
12 /avr_de/keypad/keyboard.html 245 1.47
/avr_de/rechteckgen/rectgen_m8.
13 243 1.46
html
14 /avr_en/signalgen/rectgen_m8.html 218 1.31
15 /avr_de/intro/index.html 213 1.28
16 /avr_en/AVR_ADC500.html 190 1.14
17 /avr_en/stepper/stepper.html 177 1.06
18 /avr_de/rechnen/konversion.html 173 1.04
19 /avr_de/beginner/hardware.html 171 1.03
20 /avr_en/beginner/SRAM.html 137 0.82
21 /akkuload/de/index.html 135 0.81
22 /avr_en/beginner/REGISTER.html 133 0.80
23 /avr_de/lcd4_500.html 125 0.75
24 /avr_de/rechnen/multiplikation.html 123 0.74
25 /gb_new.html 121 0.73
Sum 16,664 100.00

To top of page

Top 25 of 275 cheat pages , sorted by number of files

N cheat pages times %


1 2,750 12.80
2 /index.html 1,731 8.06
3 /avr_en/index.html 1,518 7.07
4 /avr_de/index.html 1,305 6.08
5 /avr_en/beginner/RIGHT.html 543 2.53
6 /avr_en/AVR_DAC.html 446 2.08
7 /avr_de/stepper/stepper.html 421 1.96
8 /avr_en/beginner/HARDWARE.html 368 1.71
9 /avr_en/keypad/keyboard.html 359 1.67
10 /avr_de/keypad/keyboard.html 308 1.43
11 /avr_de/avr_dac.html 302 1.41
12 /avr_de/beginner/rechts.html 301 1.40
13 /avr_de/fcount/fcount_m8.html 291 1.35
14 /avr_en/beginner/REGISTER.html 268 1.25
/avr_de/rechteckgen/rectgen_m8.
15 232 1.08
html
16 /avr_en/AVR_ADC500.html 228 1.06
17 /akkuload/de/index.html 227 1.06
18 /avr_de/beginner/hardware.html 226 1.05
19 /avr_en/beginner/JUMP.html 218 1.02
20 /avr_de/praesentation/index.html 210 0.98
21 /avr_de/beginner/sprung.html 203 0.95
22 /avr_en/beginner/SRAM.html 200 0.93
23 /avr_de/intro/index.html 198 0.92
24 /avr_en/signalgen/rectgen_m8.html 197 0.92
25 /avr_en/stepper/stepper.html 192 0.89
Sum 21,477 100.00

To top of page

Top 25 of 231 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 6,951 16.33
2 /avr_en/beginner/index.html 4,878 11.46
3 /avr_de/beginner/index.html 3,192 7.50
4 / 2,965 6.97
5 /avr_en/index.html 2,545 5.98
6 /avr_en/ 2,381 5.59
7 /avr_en/beginner/RIGHT.html 2,277 5.35
8 /avr_de/beginner/rechts.html 1,734 4.07
9 /avr_en/beginner/LEFT.html 1,731 4.07
10 /avr_de/beginner/links.html 1,235 2.90
11 /sitemap_de.html 1,004 2.36
12 /avr_de/apps.html 767 1.80
13 /sitemap_en.html 739 1.74
14 /index.html 588 1.38
15 /avr_de/interrupts/index.html 579 1.36
16 /avr_de/zeitschleifen/index.html 543 1.28
17 /avr_en/calc/index.html 469 1.10
18 /avr_de/avr_tut.html 451 1.06
19 /avr_en/AVR_TUT.html 433 1.02
20 /avr_de/ 390 0.92
21 /weblox_de/index.html 311 0.73
22 /avr_de/rechnen/index.html 310 0.73
23 /weblox_en/index.html 294 0.69
24 /avr_en/APPS.html 287 0.67
/avr_de/beginner/commands.
25 230 0.54
html
Sum 42,564 100.00

To top of page

Top 25 of 997 external referrers , sorted by number of files

N external referrers times %


1 - 22,183 84.32
2 http://www.webring.com/hub?ring=avr 172 0.65
3 http://www.mikrocontroller.net/articles/AVR 164 0.62
4 http://www.dg4fac.de/linksunten.html 76 0.29
5 http://www.rowalt.de/mc/avr/linksd.htm 71 0.27
6 http://avr-asm.tripod.com/ 70 0.27
7 http://de.wikipedia.org/wiki/R2R-Netzwerk 67 0.25
http://www.avrfreaks.net/index.php?
8 name=PNphpBB2&file=viewtopic&t=7067 66 0.25
3
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
9 65 0.25
ESC_by1_bz0_bs0.html
10 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 65 0.25
11 http://www.dg4fac.de/rechtsunten.html 58 0.22
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
12 55 0.21
kurs.htm
13 http://www.educypedia.be/electronics/avr.htm 54 0.21
http://electrons.psychogenic.com/modules/arms/art/3/
14 AVRGCCProgrammingG 53 0.20
uide.php
15 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 53 0.20
16 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 53 0.20
17 http://www.mikrocontroller.net/articles/Linksammlung 41 0.16
18 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 39 0.15
19 http://www.attiny.com/avrlinks.htm 36 0.14
20 http://www.serasidis.gr/link.htm 32 0.12
21 http://frank.bol.ucla.edu/avr.htm 31 0.12
22 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 30 0.11
http://www.avrfreaks.net/index.php?
23 name=PNphpBB2&file=viewtopic&t=3698 29 0.11
8
24 http://www.mikrocontroller.net/topic/10424 26 0.10
25 http://circuit.lt/?section=sch&page=avr.isp.lpt 26 0.10
Sum 26,309 100.00

To top of page

Top 25 of 206 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 5,812 42.71
2 http://www.google.com 2,767 20.34
3 http://www.google.at 391 2.87
4 http://www.google.co.in 384 2.82
5 http://www.google.co.uk 276 2.03
6 http://www.google.ch 230 1.69
7 http://www.google.nl 219 1.61
8 http://www.google.pl 206 1.51
9 http://www.google.ca 188 1.38
10 http://www.google.co.id 113 0.83
11 http://www.google.hu 111 0.82
http://www.google.com.
12 110 0.81
au
13 http://www.google.fi 108 0.79
14 http://www.google.se 107 0.79
15 http://www.google.cz 107 0.79
16 http://www.google.gr 103 0.76
17 http://www.google.it 101 0.74
18 http://www.google.ro 94 0.69
19 http://search.live.com 87 0.64
20 http://search.yahoo.com 79 0.58
21 http://www.google.be 79 0.58
http://de.search.yahoo.
22 73 0.54
com
23 http://www.google.fr 73 0.54
http://www.google.com.
24 66 0.49
vn
http://www.google.com.
25 64 0.47
br
Sum 13,607 100.00

To top of page

Top 25 of 7827 search strings , sorted by number of files

N search strings times %


1 avr tutorial 378 2.78
2 avr assembler 222 1.63
3 avr 200 1.47
4 avr programming 143 1.05
5 attiny13 134 0.98
6 assembler 129 0.95
7 avr assembly 104 0.76
8 assembler tutorial 84 0.62
9 avr asm 78 0.57
10 ATtiny13 73 0.54
11 atmega8 66 0.49
12 avr assembler tutorial 62 0.46
13 AVR 51 0.37
14 avr asm tutorial 51 0.37
15 assembler commands 48 0.35
16 stk500 42 0.31
17 avr programing 40 0.29
18 AVR tutorial 40 0.29
19 avr assembly tutorial 38 0.28
20 avr keypad 35 0.26
21 assembler avr 33 0.24
22 avr tutorials 33 0.24
23 STK500 31 0.23
schrittmotor
24 30 0.22
steuerung
25 atmega16 29 0.21
Sum 13,607 100.00

To top of page

Top 10 of 10 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 347,368 89.21
2 304 Not changed 37,791 9.71
3 206 Partial information 2,336 0.60
4 404 File not found 827 0.21

http://www.avr-asm-tutorial.net/weblox_en/2008m12.html (1 of 2)1/20/2009 8:06:42 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 301 Permanently moved 809 0.21


6 403 Forbidden 81 0.02
7 405 Method not allowed 76 0.02
8 300 Multiple choices 63 0.02
9 400 Error in request 5 0.00
10 xxx Unknown error 5 0.00
Sum 389,361 100.00

To top of page

Top 25 of 244 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 223 26.96
2 /beginner_de.pdf 104 12.58
3 /MarkAny/Websafer/MaSiteInfo.ini 33 3.99
4 /_vti_inf.html 26 3.14
5 /avr_de/intro/ppt/beispiel10_snd.wav 23 2.78
/_vti_bin/owssvr.dll?
6 20 2.42
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
7 19 2.30
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
8 18 2.18
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
9 18 2.18
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
10 /avr_de/praesentation/favicon.ico 12 1.45
11 /avr_de/praesentation/favicon.gif 12 1.45
12 /sitemap.xml 8 0.97
/_vti_bin/owssvr.dll?
13 7 0.85
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
14 7 0.85
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
15 20AVR-Assemble 5 0.60
r-Dateien/links.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
16 20la 5 0.60
nguage_files/LEFT.htm
17 /avr_en/keypad/index.htm 3 0.36
18 /avr_en/stepper/index.htm 3 0.36
19 /avr_en/eggtimer/index.htm 3 0.36
20 /avr_en/signalgen/index.htm 3 0.36
/privat/magloop/errors.php?error=http://flowskatepark.org/WebCalendar-
21 3 0.36
1.0.4/includes/mod_poll.txt??
/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/includes/
22 3 0.36
mod_poll.txt??
/privat/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/in
23 3 0.36
cludes/mod_poll.txt??
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
24 20AVR-Assemble 2 0.24
r-Dateien/rechts.htm
/avr_en/source/R2R-network-2520calculation-2520tool,-2520(C)2004-2520i
25 2 0.24
nfo-40avr-asm-tutorial.net
Sum 827 100.00

To top of page

Top 25 of 243 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 209,613 53.84
2 Mozilla/4.0 140,460 36.07
3 Opera/9.62 8,855 2.27
4 Opera/9.63 3,274 0.84
5 Yanga 2,510 0.64
6 Mozilla/4.5 2,255 0.58
7 Opera/9.60 1,725 0.44
8 - 1,678 0.43
9 Opera/9.61 1,555 0.40
10 Opera/9.52 1,470 0.38
11 Opera/9.51 1,347 0.35
12 msnbot/1.1 1,236 0.32
Googlebot-
13 1,054 0.27
Image/1.0
14 FDM 2.x 961 0.25
15 Opera/9.50 910 0.23
16 Yandex/1.01.001 825 0.21
17 Xaldon 756 0.19
18 msnbot-media/1.1 733 0.19
19 Opera/9.27 675 0.17
20 msnbot-media/1.0 485 0.12
21 Opera/9.25 445 0.11
22 ichiro/3.0 445 0.11
23 Opera/9.21 428 0.11
24 Safari/5525.27.1 319 0.08
25 Safari5525.27.1 298 0.08
Sum 389,361 100.00

To top of page

Top 25 of 501 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 79,040 20.30
2 MSIE 7.0 76,730 19.71
3 MSIE 6.0 51,609 13.25
4 Firefox/3.0.5 41,336 10.62
5 Gecko 10,598 2.72
6 Firefox/2.0.0.18 9,502 2.44
7 Opera/9.62 8,848 2.27
8 unknown 7,773 2.00
9 Firefox/3.0.4 6,365 1.63
10 Firefox/3.0.3 5,856 1.50
11 Firefox/3.0.1 5,842 1.50
12 Slurp 5,373 1.38
13 Firefox/3.0.5 4,580 1.18
14 FDM 3,532 0.91
15 Opera/9.63 3,255 0.84
16 Firefox/2.0.0.20 3,254 0.84
17 Firefox/3.0 2,651 0.68
18 HTTrack 3.0x 2,250 0.58
19 MSIE 5.0 2,114 0.54
20 Googlebot/2.1 1,825 0.47
21 Opera/9.60 1,706 0.44
22 Opera/9.61 1,555 0.40
23 Firefox/2.0.0.14 1,525 0.39
24 Firefox/2.0.0.6 1,477 0.38
25 Opera/9.52 1,470 0.38
Sum 389,361 100.00

To top of page

Top 25 of 71 operating systems , sorted by number of files

N operating systems times %


1 Windows 163,590 42.01
2 Windows NT 5.1 126,503 32.49
3 unknown 27,159 6.98
4 Linux i686 21,466 5.51
5 Windows NT 6.0 20,144 5.17
6 Windows NT 5.0 6,132 1.57
7 Windows 98 4,626 1.19
8 Linux x86_64 3,843 0.99
9 Mac OS X 10.5 2,214 0.57
10 Mac OS X 10_5_5 2,079 0.53
11 Windows NT 4.0 1,859 0.48
12 Windows NT 5.2 1,440 0.37
13 Linux 1,049 0.27
14 Mac OS X 1,015 0.26
15 Win16 831 0.21
16 Windows XP 5.1 760 0.20
17 Linux i686 750 0.19
18 Mac OS X 10_5_6 681 0.17
Mac OS X
19 676 0.17
10_4_11
20 Mac OS X 10.4 590 0.15
21 Windows 6.0 284 0.07
22 Mac OS X Mach-O 142 0.04
23 Mac OS X 10_5_4 141 0.04
24 Linux 2.6.24.4 135 0.03
25 Windows 32-bit 130 0.03
Sum 389,361 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 12,407 3.19
2 01 10,820 2.78
3 02 7,431 1.91
4 03 7,257 1.86
5 04 5,972 1.53
6 05 5,327 1.37
7 06 6,705 1.72
8 07 8,402 2.16
9 08 12,979 3.33
10 09 14,300 3.67
11 10 16,581 4.26
12 11 18,919 4.86
13 12 22,225 5.71
14 13 21,875 5.62
15 14 21,629 5.55
16 15 22,305 5.73
17 16 22,506 5.78
18 17 23,988 6.16
19 18 21,054 5.41
20 19 22,853 5.87
21 20 22,981 5.90
22 21 22,751 5.84
23 22 20,688 5.31
24 23 17,406 4.47
Sum 389,361 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008m12.html (2 of 2)1/20/2009 8:06:42 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Monthly sorted index ==> Log 2008m11

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , month 11

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 22236 IPs and host names , sorted by number of files

N IPs and host names times %


1 66.249.72.79=crawl-66-249-72-79.googlebot.com 3,059 0.77
2 67.195.37.109=llf320031.crawl.yahoo.net 2,649 0.67
3 83.160.188.158=atena-2.demon.nl 2,282 0.57
4 91.205.124.9=(not found) 2,020 0.51
5 84.181.247.241=p54B5F7F1.dip.t-dialin.net 1,262 0.32
6 208.111.154.16=crawl2.nat.svl.searchme.com 987 0.25
7 80.91.174.42=undefined.datagroup.com.ua 895 0.22
8 150.214.40.115=jano5.sci.uma.es 789 0.20
9 79.234.165.241=p4FEAA5F1.dip0.t-ipconnect.de 758 0.19
10 93.158.148.31=spider11.yandex.ru 739 0.19
11 200.75.53.86=corporat200-075053086.sta.etb.net.co 738 0.19
12 150.214.40.116=jano6.sci.uma.es 710 0.18
13 194.254.62.54=www.lyc-edouardbranly.ac-poitiers.fr 643 0.16
14 193.144.2.249=pub249.unirioja.es 633 0.16
15 91.16.156.58=p5B109C3A.dip0.t-ipconnect.de 630 0.16
89.16.140.231=cable-89-16-140-231.cust.blue-cable.
16 624 0.16
de
17 79.129.247.65=athedsl-4458321.home.otenet.gr 616 0.15
18 66.90.73.188=(not found) 611 0.15
19 84.77.129.90=(not found) 559 0.14
20 89.61.245.32=Zf520.z.pppool.de 532 0.13
21 92.80.11.94=(not found) 526 0.13
22 78.111.65.140=(not found) 525 0.13
23 89.61.201.7=Zc907.z.pppool.de 509 0.13
24 202.153.240.100=dsl-153.240-100.static.indo.net.id 501 0.13
25 194.39.218.10=http-v.fe.bosch.de 493 0.12
Sum 397,976 100.00

To top of page

Top 25 of 22236 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 66.249.72.79=crawl-66-249-72-79.googlebot.com 42,406 1.03
2 67.195.37.109=llf320031.crawl.yahoo.net 41,006 1.00
3 91.205.124.9=(not found) 34,903 0.85
4 80.91.174.42=undefined.datagroup.com.ua 28,267 0.69
5 83.160.188.158=atena-2.demon.nl 28,170 0.68
6 66.90.73.188=(not found) 18,773 0.46
7 77.22.123.118=(not found) 18,629 0.45
8 202.152.39.154=(not found) 18,356 0.45
9 79.234.165.241=p4FEAA5F1.dip0.t-ipconnect.de 17,640 0.43
10 194.254.62.54=www.lyc-edouardbranly.ac-poitiers.fr 17,034 0.41
11 84.181.247.241=p54B5F7F1.dip.t-dialin.net 16,918 0.41
12 193.144.2.249=pub249.unirioja.es 16,411 0.40
13 91.16.156.58=p5B109C3A.dip0.t-ipconnect.de 16,285 0.40
89.16.140.231=cable-89-16-140-231.cust.blue-cable.
14 16,086 0.39
de
15 70.50.6.234=bas18-toronto12-1177683690.dsl.bell.ca 15,863 0.39
16 79.129.247.65=athedsl-4458321.home.otenet.gr 15,200 0.37
17 82.207.242.19=muedsl-82-207-242-019.citykom.de 12,219 0.30
18 141.34.7.112=znzelw1.ifh.de 11,221 0.27
19 93.134.178.102=mnch-5d86b266.pool.einsundeins.de 9,368 0.23
20 87.170.67.46=p57AA432E.dip0.t-ipconnect.de 8,820 0.21
21 84.77.129.90=(not found) 7,970 0.19
22 91.144.1.34=(not found) 7,909 0.19
23 88.131.106.16=(not found) 7,819 0.19
24 79.219.54.233=p4FDB36E9.dip0.t-ipconnect.de 7,806 0.19
25 217.235.194.135=pD9EBC287.dip.t-dialin.net 7,727 0.19
Sum 4,112,682 100.00

To top of page

Top 25 of 4160 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 507 2.84
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 458 2.56
3 208.111.154.16=crawl2.nat.svl.searchme.com 213 1.19
4 208.111.154.15=crawl1.nat.svl.searchme.com 195 1.09
5 66.235.124.3=crawler5003.ask.com 155 0.87
6 88.131.106.16=(not found) 141 0.79
7 81.52.143.26=natcrawlbloc05.net.m1.fti.net 138 0.77
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 136 0.76
9 81.52.143.16=natcrawlbloc03.net.m1.fti.net 131 0.73
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 124 0.69
11 193.47.80.44=crawl8.exabot.com 108 0.60
65.55.209.168=msnbot-65-55-209-168.search.msn.
12 75 0.42
com
13 193.252.149.16=natcrawlbloc04.net.s1.fti.net 70 0.39
65.55.209.153=msnbot-65-55-209-153.search.msn.
14 62 0.35
com
65.55.209.151=msnbot-65-55-209-151.search.msn.
15 60 0.34
com
16 38.99.13.125=crawl-4.cuill.com 56 0.31
17 208.111.154.27=v27.nat.svl.searchme.com 54 0.30
18 65.55.212.136=(not found) 52 0.29
65.55.209.166=msnbot-65-55-209-166.search.msn.
19 50 0.28
com
20 77.79.25.43=hst-25-43.splius.lt 47 0.26
21 88.118.153.89=(not found) 47 0.26
65.55.209.158=msnbot-65-55-209-158.search.msn.
22 47 0.26
com
65.55.209.165=msnbot-65-55-209-165.search.msn.
23 46 0.26
com
24 212.254.176.2=adsl-176-2-fixip.tiscali.ch 45 0.25
25 208.44.234.50=(not found) 45 0.25
Sum 17,874 100.00

To top of page

Top 25 of 138 countries of origin , sorted by number of files

N countries of origin times %


1 net 106,991 26.88
2 Germany 86,550 21.75
3 (unresolved) 70,865 17.81
4 com 25,949 6.52
5 Austria 10,122 2.54
6 Poland 9,783 2.46
7 Netherlands 7,108 1.79
8 Switzerland 5,454 1.37
9 Italy 4,365 1.10
10 Spain 3,263 0.82
11 Hungary 3,186 0.80
12 Indonesia 2,824 0.71
13 Mexico 2,812 0.71
14 edu 2,778 0.70
15 Czech Republic 2,697 0.68
16 Greece 2,618 0.66
17 India 2,617 0.66
18 Australia 2,587 0.65
19 Belgium 2,375 0.60
20 Lithuania 2,366 0.59
21 Canada 2,361 0.59
22 Brazil 2,243 0.56
23 Sweden 2,204 0.55
24 Romania 2,156 0.54
25 Russian Federation 2,065 0.52
Sum 397,976 100.00

To top of page

Top 25 of 209 pathes , sorted by number of files

N pathes times %
1 /common/ 138,559 34.82
2 /avr_gra/ 69,577 17.48
3 / 46,963 11.80
4 /avr_en/beginner/ 17,380 4.37
5 /avr_de/beginner/ 13,140 3.30
6 /avr_en/ 12,390 3.11
7 /avr_de/ 12,000 3.02
8 /avr_en/calc/ 8,523 2.14
9 /avr_de/rechnen/ 6,236 1.57
10 /avr_de/fcount/ 5,867 1.47
11 /avr_de/stepper/ 5,395 1.36
12 /avr_en/source/ 5,015 1.26
13 /avr_de/praesentation/ 4,792 1.20
14 /avr_de/quellen/ 4,310 1.08
15 /avr_en/keypad/ 3,880 0.97
16 /avr_en/signalgen/pics/ 3,150 0.79
17 /avr_en/stepper/ 3,015 0.76
18 /gavrasm/ 3,011 0.76
19 /avr_de/keypad/ 2,974 0.75
/avr_de/rechteckgen/
20 2,896 0.73
bilder/
21 /avr_de/zeitschleifen/ 2,602 0.65
22 /avr_de/interrupts/ 2,107 0.53
23 /privat/magloop/ 1,483 0.37
24 /akkuload/ 1,369 0.34
25 /avr_en/signalgen/ 1,298 0.33
Sum 397,976 100.00

To top of page

Top 25 of 209 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 794,300 19.31
2 /avr_gra/ 550,773 13.39
3 /avr_de/intro/pdf/ 313,107 7.61
4 / 256,403 6.23
5 /avr_de/fcount/ 226,964 5.52
6 /avr_de/ 184,891 4.50
7 /avr_en/ 168,037 4.09
8 /avr_en/beginner/ 146,233 3.56
9 /avr_de/stepper/ 144,689 3.52
10 /avr_de/beginner/ 125,131 3.04
11 /gavrasm/v21/ 88,321 2.15
12 /avr_en/signalgen/pics/ 84,615 2.06
/avr_de/rechteckgen/
13 79,012 1.92
bilder/
14 /avr_en/calc/ 78,399 1.91
15 /avr_en/stepper/ 76,668 1.86
16 /privat/magloop/ 72,957 1.77
17 /common/ 66,189 1.61
18 /avr_de/rechnen/ 56,403 1.37
19 /avr_en/signalgen/ 47,103 1.15
20 /avr_de/rechteckgen/ 42,036 1.02
21 /avr_de/intro/ppt/ 39,934 0.97
22 /weblox_de/ 37,812 0.92
23 /akkuload/ 33,808 0.82
24 /weblox_en/ 33,339 0.81
25 /avr_en/keypad/ 28,059 0.68
Sum 4,112,682 100.00

To top of page

Top 25 of 1970 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 20,551 5.16
2 /avr_gra/RingLogo.jpg 10,843 2.72
3 /common/akkuload.gif 8,959 2.25
4 /common/app.gif 8,958 2.25
/common/download.
5 8,948 2.25
gif
/common/knowhow.
6 8,945 2.25
gif
7 /avr_gra/stk_lcd.jpg 8,929 2.24
8 /common/gavrasm.gif 8,926 2.24
9 /common/clock.gif 8,925 2.24
10 /common/example.gif 8,924 2.24
11 /common/calc.gif 8,913 2.24
12 /common/beginner.gif 8,905 2.24
/common/gavrasmw.
13 8,903 2.24
gif
14 /common/adc.gif 8,898 2.24
15 /common/keyb.gif 8,893 2.23
16 /common/r2r.gif 8,874 2.23
17 /common/hardware.gif 8,873 2.23
18 /index.html 6,326 1.59
19 /avr_en/index.html 5,285 1.33
20 /avr_de/index.html 5,136 1.29
21 /avr_2313.gif 5,089 1.28
22 /dg4fac.gif 4,833 1.21
23 /avr-asm-tutorial.gif 4,796 1.21
24 /avr_gra/2313.gif 4,594 1.15
25 /common/delay.gif 4,579 1.15
Sum 397,976 100.00

To top of page

Top 25 of 1970 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 251,528 6.12
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 165,396 4.02
3 /avr_de/index.html 114,963 2.80
4 /avr_en/index.html 107,675 2.62
/avr_de/praesentation/Teil_5b_Beispiel01_02.
5 100,512 2.44
pdf
6 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 86,961 2.11
7 /avr_2313.gif 85,401 2.08
8 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 84,778 2.06
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 82,811 2.01
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 68,052 1.65
11 /dg4fac.gif 51,185 1.24
12 /avr_gra/pwm_simul.jpg 47,911 1.16
13 /avr_gra/r2r_hardware.jpg 45,091 1.10
14 /avr_de/fcount/dscf0004.jpg 44,529 1.08
15 /favicon.ico 40,267 0.98
16 /avr_de/intro/pdf/Teil1_Prozessor.pdf 39,214 0.95
17 /avr_en/signalgen/pics/rectgen_wiring.jpg 38,630 0.94
18 /avr_de/fcount/dscf0005.jpg 38,481 0.94
19 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 37,662 0.92
20 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 37,565 0.91
21 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 36,585 0.89
22 /avr_de/fcount/dscf0001.jpg 36,342 0.88
23 /avr_de/stepper/stepper_v1.gif 35,771 0.87
24 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 34,522 0.84
25 /avr_gra/exp2313.gif 34,017 0.83
Sum 4,112,682 100.00

To top of page

Top 25 of 581 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 6,326 7.28
2 /avr_en/index.html 5,285 6.08
3 /avr_de/index.html 5,136 5.91
4 /avr_en/beginner/index.html 3,040 3.50
5 /avr_en/beginner/RIGHT.html 2,948 3.39
6 /avr_en/beginner/LEFT.html 2,931 3.37
7 /avr_de/beginner/index.html 2,002 2.30
8 /avr_de/beginner/links.html 1,935 2.23
9 /avr_de/beginner/rechts.html 1,926 2.21
/avr_en/beginner/HARDWARE.
10 1,145 1.32
html
11 /avr_en/beginner/REGISTER.html 1,027 1.18
12 /avr_de/beginner/hardware.html 846 0.97
13 /avr_en/AVR_DAC.html 825 0.95
14 /avr_en/beginner/JUMP.html 819 0.94
15 /avr_en/keypad/keyboard.html 781 0.90
16 /avr_de/stepper/stepper.html 743 0.85
17 /avr_de/beginner/register.html 735 0.85
18 /avr_en/beginner/TOOLS.html 721 0.83
19 /avr_de/praesentation/index.html 716 0.82
20 /avr_de/apps.html 690 0.79
21 /avr_en/beginner/PORTS.html 664 0.76
22 /avr_de/beginner/werkzeuge.html 659 0.76
23 /avr_de/beginner/sprung.html 656 0.75
24 /avr_en/beginner/SRAM.html 650 0.75
25 /avr_de/beginner/ports.html 641 0.74
Sum 86,954 100.00

To top of page

Top 25 of 581 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 114,963 11.66
2 /avr_en/index.html 107,675 10.92
3 /index.html 33,034 3.35
4 /avr_en/beginner/RIGHT.html 21,064 2.14
5 /avr_en/beginner/JUMP.html 19,246 1.95
6 /avr_de/beginner/sprung.html 18,032 1.83
7 /avr_de/dcf77uhr.html 17,820 1.81
8 /gb_new.html 17,230 1.75
9 /avr_en/keypad/keyboard.html 15,832 1.61
10 /avr_en/beginner/CALC.html 15,074 1.53
11 /avr_de/beginner/rechnen.html 13,843 1.40
12 /avr_de/beginner/rechts.html 13,671 1.39
13 /avr_en/beginner/LEFT.html 13,385 1.36
14 /avr_de/keypad/keyboard.html 12,565 1.27
15 /avr_en/beginner/REGISTER.html 12,061 1.22
16 /avr_en/AVR_DAC.html 11,971 1.21
17 /avr_de/stepper/stepper.html 11,184 1.13
/avr_en/beginner/COMMANDS.
18 11,141 1.13
html
19 /avr_de/beginner/pdetail.html 10,630 1.08
/avr_de/rechteckgen/rectgen_m8.
20 10,516 1.07
html
21 /avr_en/signalgen/rectgen_m8.html 10,467 1.06
22 /avr_de/avr_dac.html 10,404 1.06
23 /avr_en/beginner/PDETAIL.html 10,248 1.04
24 /avr_en/AVR_ADC500.html 9,809 0.99
25 /avr_de/beginner/commands.html 9,746 0.99
Sum 985,981 100.00

To top of page

Top 25 of 588 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 10,839 18.80
2 /avr_gra/stk_lcd.jpg 8,928 15.49
3 /avr_gra/8515.jpg 2,229 3.87
4 /avr_gra/exp2313g.jpg 1,877 3.26
5 /avr_gra/avr_isp.jpg 1,830 3.17
6 /avr_gra/exp_2313.jpg 1,791 3.11
7 /avr_gra/r2r_wave.jpg 1,516 2.63
8 /avr_gra/r2r_sawtooth.jpg 1,364 2.37
9 /avr_gra/r2r_hardware.jpg 1,280 2.22
10 /avr_gra/r2r_sawtoothupperbound.jpg 1,260 2.19
11 /avr_gra/r2r_triangle.jpg 1,258 2.18
12 /avr_gra/r2r_upperbound.jpg 1,250 2.17
13 /avr_gra/r2r_sawtooth741.jpg 1,249 2.17
14 /avr_gra/AT90S8515.jpg 1,101 1.91
15 /avr_gra/apps.jpg 898 1.56
16 /avr_gra/adc8conn.jpg 878 1.52
17 /avr_gra/pwm_simul.jpg 874 1.52
18 /avr_de/stepper/stepper_sm.jpg 758 1.31
19 /avr_de/stepper/kp4m4-001.jpg 720 1.25
20 /avr_de/stepper/supply.jpg 705 1.22
21 /avr_en/signalgen/pics/rectgen_280.jpg 704 1.22
22 /avr_de/stepper/driver.jpg 701 1.22
23 /avr_de/praesentation/zuendtester.jpg 640 1.11
24 /akkuload/dscf0030s.jpg 639 1.11
/avr_de/rechteckgen/bilder/rectgen_280.
25 589 1.02
jpg
Sum 57,651 100.00

To top of page

Top 25 of 431 GIF-files , sorted by number of files

N GIF-files times %
1 /common/akkuload.gif 8,959 4.28
2 /common/app.gif 8,956 4.28
/common/download.
3 8,945 4.27
gif
/common/knowhow.
4 8,943 4.27
gif
5 /common/gavrasm.gif 8,924 4.26
6 /common/clock.gif 8,923 4.26
7 /common/example.gif 8,920 4.26
8 /common/calc.gif 8,911 4.26
9 /common/beginner.gif 8,905 4.25
/common/gavrasmw.
10 8,901 4.25
gif
11 /common/adc.gif 8,896 4.25
12 /common/keyb.gif 8,891 4.25
13 /common/r2r.gif 8,874 4.24
14 /common/hardware.gif 8,873 4.24
15 /avr_2313.gif 5,089 2.43
16 /dg4fac.gif 4,829 2.31
17 /avr-asm-tutorial.gif 4,796 2.29
18 /avr_gra/2313.gif 4,594 2.19
19 /common/delay.gif 4,579 2.19
20 /common/ints.gif 4,569 2.18
21 /common/tn13.gif 4,561 2.18
22 /avr_gra/exp2313.gif 1,939 0.93
23 /avr_gra/avr_isp.gif 1,817 0.87
24 /avr_gra/isp6pin.gif 1,796 0.86
25 /avr_gra/isp10pin.gif 1,796 0.86
Sum 209,316 100.00

To top of page

Top 25 of 220 entry pages , sorted by number of files

N entry pages times %


1 /index.html 2,808 16.11
2 /avr_en/index.html 1,823 10.46
3 /avr_de/index.html 1,596 9.16
4 /avr_en/beginner/index.html 913 5.24
5 /avr_de/beginner/index.html 503 2.89
6 /avr_en/AVR_DAC.html 447 2.56
7 /avr_de/stepper/stepper.html 387 2.22
8 /avr_de/avr_dac.html 344 1.97
9 /avr_en/beginner/HARDWARE.html 314 1.80
10 /avr_de/fcount/fcount_m8.html 284 1.63
11 /avr_en/keypad/keyboard.html 263 1.51
12 /avr_en/signalgen/rectgen_m8.html 259 1.49
/avr_de/rechteckgen/rectgen_m8.
13 241 1.38
html
14 /avr_de/keypad/keyboard.html 238 1.37
15 /avr_en/AVR_ADC500.html 237 1.36
16 /avr_en/stepper/stepper.html 189 1.08
17 /avr_de/intro/index.html 180 1.03
18 /avr_de/rechnen/konversion.html 169 0.97
19 /gb_new.html 167 0.96
20 /avr_en/beginner/SRAM.html 166 0.95
21 /avr_de/rechnen/multiplikation.html 161 0.92
22 /avr_de/beginner/hardware.html 160 0.92
23 /avr_de/beginner/diraus.html 151 0.87
24 /avr_de/avr_adc500.html 145 0.83
25 /avr_en/beginner/REGISTER.html 133 0.76
Sum 17,429 100.00

To top of page

Top 25 of 309 cheat pages , sorted by number of files

N cheat pages times %


1 2,234 10.05
2 /index.html 1,736 7.81
3 /avr_en/index.html 1,460 6.57
4 /avr_de/index.html 1,352 6.08
5 /avr_en/beginner/RIGHT.html 597 2.68
6 /avr_en/AVR_DAC.html 504 2.27
7 /avr_en/beginner/HARDWARE.html 430 1.93
8 /avr_de/stepper/stepper.html 405 1.82
9 /avr_en/keypad/keyboard.html 390 1.75
10 /avr_de/avr_dac.html 357 1.61
11 /avr_de/beginner/rechts.html 334 1.50
12 /avr_de/keypad/keyboard.html 319 1.43
13 /avr_en/beginner/REGISTER.html 295 1.33
14 /avr_de/fcount/fcount_m8.html 279 1.25
15 /avr_en/AVR_ADC500.html 271 1.22
16 /avr_en/signalgen/rectgen_m8.html 259 1.16
17 /avr_de/beginner/hardware.html 237 1.07
18 /avr_en/beginner/JUMP.html 229 1.03
19 /avr_en/beginner/SRAM.html 228 1.03
/avr_de/rechteckgen/rectgen_m8.
20 219 0.98
html
21 /avr_de/beginner/rechnen.html 212 0.95
22 /avr_en/stepper/stepper.html 201 0.90
23 /avr_de/beginner/werkzeuge.html 192 0.86
24 /akkuload/de/index.html 190 0.85
25 /avr_de/beginner/diraus.html 188 0.85
Sum 22,236 100.00

To top of page

Top 25 of 206 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 6,780 15.57
2 /avr_en/beginner/index.html 5,140 11.80
3 /avr_de/beginner/index.html 3,415 7.84
4 / 3,050 7.00
5 /avr_en/index.html 2,888 6.63
6 /avr_en/ 2,244 5.15
7 /avr_en/beginner/RIGHT.html 2,235 5.13
8 /avr_de/beginner/rechts.html 1,931 4.43
9 /avr_en/beginner/LEFT.html 1,832 4.21
10 /avr_de/beginner/links.html 1,383 3.18
11 /sitemap_de.html 1,152 2.65
12 /sitemap_en.html 751 1.72
13 /index.html 642 1.47
14 /avr_de/apps.html 634 1.46
15 /avr_de/interrupts/index.html 568 1.30
16 /avr_de/zeitschleifen/index.html 515 1.18
17 /avr_en/calc/index.html 483 1.11
18 /avr_en/AVR_TUT.html 474 1.09
19 /avr_de/ 473 1.09
20 /avr_de/avr_tut.html 441 1.01
21 /avr_en/APPS.html 318 0.73
22 /avr_de/beginner/commands.html 302 0.69
23 /weblox_en/index.html 269 0.62
24 /avr_de/rechnen/index.html 266 0.61
/avr_en/beginner/COMMANDS.
25 234 0.54
html
Sum 43,546 100.00

To top of page

Top 25 of 1025 external referrers , sorted by number of files

N external referrers times %


1 - 23,497 83.75
2 http://www.mikrocontroller.net/articles/AVR 191 0.68
3 http://www.webring.com/hub?ring=avr 127 0.45
4 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 97 0.35
5 http://de.wikipedia.org/wiki/R2R-Netzwerk 85 0.30
6 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 85 0.30
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
7 79 0.28
ESC_by1_bz0_bs0.html
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
8 78 0.28
kurs.htm
9 http://www.educypedia.be/electronics/avr.htm 75 0.27
10 http://avr-asm.tripod.com/ 74 0.26
11 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 69 0.25
http://www.avrfreaks.net/index.php?
12 name=PNphpBB2&file=viewtopic&t=7067 66 0.24
3
13 http://www.rowalt.de/mc/avr/linksd.htm 60 0.21
14 http://www.dg4fac.de/linksunten.html 59 0.21
15 http://www.dg4fac.de/rechtsunten.html 57 0.20
http://electrons.psychogenic.com/modules/arms/art/3/
16 AVRGCCProgrammingG 51 0.18
uide.php
17 http://www.mikrocontroller.net/articles/Linksammlung 51 0.18
18 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 43 0.15
19 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 42 0.15
20 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 42 0.15
21 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 40 0.14
22 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 35 0.12
23 http://www.edw.com.pl/ea/asm_avr_jezyk.html 34 0.12
24 http://circuit.lt/?section=sch&page=avr.isp.lpt 32 0.11
25 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 30 0.11
Sum 28,057 100.00

To top of page

Top 25 of 210 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 6,141 42.62
2 http://www.google.com 2,721 18.88
3 http://www.google.at 450 3.12
4 http://www.google.co.in 391 2.71
5 http://www.google.co.uk 298 2.07
6 http://www.google.ch 270 1.87
7 http://www.google.pl 249 1.73
8 http://www.google.nl 223 1.55
9 http://www.google.ca 188 1.30
10 http://www.google.com.au 172 1.19
11 http://www.google.se 135 0.94
12 http://www.google.co.id 124 0.86
13 http://www.google.ro 122 0.85
14 http://www.google.fi 105 0.73
15 http://www.google.com.br 101 0.70
16 http://www.google.it 99 0.69
17 http://search.live.com 96 0.67
18 http://www.google.hu 92 0.64
19 http://de.search.yahoo.com 85 0.59
20 http://www.google.com.mx 84 0.58
21 http://www.google.be 82 0.57
22 http://www.google.cz 81 0.56
23 http://www.google.gr 81 0.56
http://www.stumbleupon.
24 79 0.55
com
25 http://www.google.fr 78 0.54
Sum 14,409 100.00

To top of page

Top 25 of 8392 search strings , sorted by number of files

N search strings times %


1 avr tutorial 377 2.62
2 avr assembler 255 1.77
3 avr 192 1.33
4 avr programming 144 1.00
5 assembler 139 0.96
6 attiny13 136 0.94
7 avr assembly 90 0.62
8 assembler tutorial 90 0.62
9 avr asm 90 0.62
http://www.avr-asm-tutorial.net/avr_en/beginner/index.
10 77 0.53
html
11 atmega8 60 0.42
12 avr assembler tutorial 58 0.40
13 assembler commands 51 0.35
14 stk500 45 0.31
15 ATtiny13 42 0.29
16 AVR 41 0.28
17 gavrasm 40 0.28
18 AVR tutorial 40 0.28
19 avr asm tutorial 40 0.28
20 avr assembly tutorial 36 0.25
21 atmel tutorial 36 0.25
22 r2r network 35 0.24
23 AVR Assembler 35 0.24
24 Assembler 35 0.24
25 MCUCR 34 0.24
Sum 14,409 100.00

To top of page

Top 12 of 12 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 355,278 89.27
2 304 Not changed 38,631 9.71
3 206 Partial information 2,025 0.51
4 404 File not found 951 0.24

http://www.avr-asm-tutorial.net/weblox_en/2008m11.html (1 of 2)1/20/2009 8:07:01 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 301 Permanently moved 869 0.22


6 403 Forbidden 145 0.04
7 300 Multiple choices 59 0.01
8 405 Method not allowed 10 0.00
9 xxx Unknown error 5 0.00
10 401 Not authorized 1 0.00
11 xxx Unknown error 1 0.00
12 400 Error in request 1 0.00
Sum 397,976 100.00

To top of page

Top 25 of 202 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 159 16.72
2 /_vpi.xml 159 16.72
3 /beginner_de.pdf 101 10.62
4 /avr_en/source/_vpi.xml 45 4.73
5 /avr_de/praesentation/favicon.ico 34 3.58
6 /avr_de/praesentation/favicon.gif 34 3.58
/_vti_bin/owssvr.dll?
7 21 2.21
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
8 21 2.21
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
9 20 2.10
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
10 19 2.00
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
11 /_vti_inf.html 14 1.47
/_vti_bin/owssvr.dll?
12 9 0.95
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 9 0.95
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
14 20la 8 0.84
nguage_files/LEFT.htm
15 /avr_de/intro/ppt/beispiel10_snd.wav 8 0.84
/_vti_bin/owssvr.dll?
16 8 0.84
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
17 8 0.84
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
18 /avr_en/_vpi.xml 6 0.63
19 /avr_en/beginner/REGISTER.html/index.html 6 0.63
20 /sitemap.xml 5 0.53
21 /avr_en/stepper/schrittmotor_v1.html 4 0.42
22 /avr_en/quellen/schrittmotor_v1.asm 4 0.42
/modules/3rdparty/adminpart/add3rdparty.php?module=http://geeklinuxer.
23 4 0.42
co.cc/data/Gang11/id?
/_vti_bin/owssvr.dll?
24 4 0.42
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
25 4 0.42
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
Sum 951 100.00

To top of page

Top 25 of 232 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 211,480 53.14
2 Mozilla/4.0 144,163 36.22
3 Opera/9.62 6,917 1.74
4 Mozilla/4.5 4,135 1.04
5 Opera/9.60 3,035 0.76
6 Opera/9.61 2,682 0.67
7 Opera/9.52 2,386 0.60
8 Yanga 2,020 0.51
9 Opera/9.51 1,486 0.37
10 Mozilla/3.0 1,485 0.37
11 - 1,353 0.34
12 msnbot/1.1 1,351 0.34
13 Opera/9.25 1,157 0.29
Googlebot-
14 1,143 0.29
Image/1.0
15 Opera/9.50 961 0.24
16 Opera/9.27 905 0.23
17 Opera/9.26 775 0.19
18 Anonymous 741 0.19
19 Yandex/1.01.001 739 0.19
20 Teleport Pro/1.29 738 0.19
21 Wget/1.10.2 630 0.16
22 PageNest 536 0.13
23 Opera/9.24 453 0.11
24 Eurobot/1.0 366 0.09
25 Speedy 350 0.09
Sum 397,976 100.00

To top of page

Top 25 of 486 browser versions , sorted by number of files

N browser versions times %


1 MSIE 7.0 74,365 18.69
2 Firefox/3.0.3 63,705 16.01
3 MSIE 6.0 58,379 14.67
4 Firefox/3.0.4 53,935 13.55
5 Firefox/2.0.0.17 11,846 2.98
6 Firefox/2.0.0.18 10,998 2.76
7 Firefox/3.0.1 9,298 2.34
8 unknown 8,717 2.19
9 Gecko 8,567 2.15
10 Opera/9.62 6,886 1.73
11 Slurp 5,920 1.49
12 Firefox/3.0.4 4,300 1.08
13 HTTrack 3.0x 4,134 1.04
14 Firefox/3.0 3,895 0.98
15 Firefox/3.0.3 3,887 0.98
16 FDM 3,158 0.79
17 Opera/9.60 3,028 0.76
18 Opera/9.61 2,682 0.67
19 Opera/9.52 2,363 0.59
20 Firefox/2.0.0.14 2,252 0.57
21 Googlebot/2.1 1,934 0.49
22 MSIE 5.0 1,654 0.42
Gecko/2008092816
23 1,554 0.39
Iceweasel/3.0.3
24 Indy Library 1,474 0.37
25 Opera/9.51 1,465 0.37
Sum 397,976 100.00

To top of page

Top 25 of 72 operating systems , sorted by number of files

N operating systems times %


1 Windows 165,405 41.56
2 Windows NT 5.1 128,781 32.36
3 unknown 28,775 7.23
4 Linux i686 22,089 5.55
5 Windows NT 6.0 20,604 5.18
6 Windows NT 5.0 7,270 1.83
7 Windows 98 6,680 1.68
8 Linux x86_64 3,967 1.00
9 Mac OS X 10_5_5 2,570 0.65
10 Mac OS X 10.5 2,108 0.53
11 Windows NT 4.0 1,359 0.34
12 Windows NT 5.2 1,226 0.31
13 Linux 1,117 0.28
14 Win16 745 0.19
15 FreeBSD i386 649 0.16
Mac OS X
16 622 0.16
10_4_11
17 Mac OS X 609 0.15
18 Mac OS X 10.4 576 0.14
19 Windows XP 5.1 565 0.14
20 Linux i686 332 0.08
21 Windows 6.0 255 0.06
22 Windows XP 146 0.04
23 Mac OS X 10_5_4 143 0.04
24 Mac OS X Mach-O 136 0.03
25 Windows NT 111 0.03
Sum 397,976 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 11,749 2.95
2 01 8,345 2.10
3 02 6,838 1.72
4 03 6,346 1.59
5 04 6,291 1.58
6 05 7,139 1.79
7 06 7,151 1.80
8 07 8,527 2.14
9 08 12,715 3.19
10 09 15,744 3.96
11 10 16,916 4.25
12 11 21,016 5.28
13 12 20,884 5.25
14 13 21,863 5.49
15 14 22,659 5.69
16 15 23,848 5.99
17 16 23,425 5.89
18 17 20,870 5.24
19 18 24,035 6.04
20 19 24,035 6.04
21 20 23,964 6.02
22 21 23,936 6.01
23 22 22,105 5.55
24 23 17,575 4.42
Sum 397,976 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008m11.html (2 of 2)1/20/2009 8:07:01 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Monthly sorted index ==> Log 2008m10

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , month 10

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 21311 IPs and host names , sorted by number of files

N IPs and host names times %


1 67.195.37.109=llf320031.crawl.yahoo.net 3,222 0.83
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 2,836 0.73
3 117.96.107.107=(not found) 2,034 0.52
4 91.205.124.9=(not found) 2,001 0.52
5 77.46.254.36=(not found) 1,905 0.49
6 77.79.25.43=hst-25-43.splius.lt 1,679 0.43
7 117.96.114.240=(not found) 1,512 0.39
8 213.192.2.142=tlapnet.cust.sloane.cz 1,448 0.37
9 194.94.240.58=(not found) 818 0.21
10 208.111.154.16=crawl2.nat.svl.searchme.com 753 0.19
11 90.154.174.194=90-154-174-194.btc-net.bg 668 0.17
12 93.158.148.31=spider11.yandex.ru 663 0.17
13 24.2.234.252=c-24-2-234-252.hsd1.ct.comcast.net 641 0.17
14 68.142.212.235=crm76.image.search.mud.yahoo.net 630 0.16
15 149.217.1.6=www-cache2.mpi-hd.mpg.de 621 0.16
16 208.115.111.244=crawl3.dotnetdotcom.org 594 0.15
67.68.21.249=bas11-montreal02-1128535545.dsl.bell.
17 587 0.15
ca
18 202.133.89.3=(not found) 559 0.14
19 65.55.212.136=(not found) 526 0.14
20 202.87.191.134=(not found) 502 0.13
21 92.65.43.138=mail.vlietlandcollege.nl 501 0.13
22 77.105.200.39=user39.77-105-200.netatonce.net 474 0.12
23 203.99.187.40=(not found) 449 0.12
24 64.140.245.236=WPIS-64-140-245-236.worldpath.net 434 0.11
25 200.23.135.193=(not found) 431 0.11
Sum 388,072 100.00

To top of page

Top 25 of 21311 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 77.46.254.36=(not found) 65,823 1.66
2 67.195.37.109=llf320031.crawl.yahoo.net 48,289 1.22
3 66.249.72.79=crawl-66-249-72-79.googlebot.com 32,795 0.83
4 68.142.212.235=crm76.image.search.mud.yahoo.net 30,618 0.77
5 117.96.107.107=(not found) 27,453 0.69
6 91.205.124.9=(not found) 20,029 0.50
7 117.96.114.240=(not found) 18,354 0.46
8 90.154.174.194=90-154-174-194.btc-net.bg 16,887 0.43
9 149.217.1.6=www-cache2.mpi-hd.mpg.de 15,832 0.40
10 194.94.240.58=(not found) 15,579 0.39
11 84.186.52.85=p54BA3455.dip0.t-ipconnect.de 14,278 0.36
12 77.22.123.118=(not found) 13,986 0.35
13 64.140.245.236=WPIS-64-140-245-236.worldpath.net 13,578 0.34
14 84.140.65.19=p548C4113.dip0.t-ipconnect.de 12,956 0.33
15 141.6.8.89=(not found) 11,412 0.29
16 80.150.2.134=(not found) 10,433 0.26
17 203.99.187.40=(not found) 9,945 0.25
18 88.156.163.76=76.163.rze.vectranet.pl 9,334 0.24
19 77.79.25.43=hst-25-43.splius.lt 8,778 0.22
84.113.191.140=chello084113191140.2.13.vie.surfer.
20 8,367 0.21
at
21 92.229.113.78=g229113078.adsl.alicedsl.de 8,091 0.20
22 92.229.168.221=g229168221.adsl.alicedsl.de 8,068 0.20
23 64.128.171.4=64-128-171-4.static.twtelecom.net 8,066 0.20
24 80.129.67.24=p50814318.dip.t-dialin.net 7,767 0.20
25 91.10.109.248=p5B0A6DF8.dip.t-dialin.net 7,740 0.19
Sum 3,970,505 100.00

To top of page

Top 25 of 3818 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 460 2.68
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 409 2.38
3 88.134.89.107=88-134-89-107-dynip.superkabel.de 119 0.69
4 208.111.154.16=crawl2.nat.svl.searchme.com 116 0.68
5 193.252.149.15=natcrawlbloc02.net.s1.fti.net 113 0.66
6 88.131.106.16=ca0.entireweb.com 109 0.63
7 81.52.143.16=natcrawlbloc03.net.m1.fti.net 108 0.63
8 81.52.143.15=natcrawlbloc01.net.m1.fti.net 96 0.56
9 66.235.124.3=crawler5003.ask.com 91 0.53
10 68.142.212.235=crm76.image.search.mud.yahoo.net 85 0.49
11 38.99.13.125=crawl-4.cuill.com 81 0.47
65.55.209.167=msnbot-65-55-209-167.search.msn.
12 77 0.45
com
13 208.111.154.15=crawl1.nat.svl.searchme.com 75 0.44
65.55.209.165=msnbot-65-55-209-165.search.msn.
14 75 0.44
com
15 65.55.212.136=(not found) 72 0.42
16 91.205.124.9=(not found) 67 0.39
65.55.209.153=msnbot-65-55-209-153.search.msn.
17 61 0.36
com
18 193.47.80.44=crawl8.exabot.com 60 0.35
65.55.209.158=msnbot-65-55-209-158.search.msn.
19 59 0.34
com
65.55.209.164=msnbot-65-55-209-164.search.msn.
20 59 0.34
com
65.55.209.151=msnbot-65-55-209-151.search.msn.
21 57 0.33
com
22 80.108.152.73=chello080108152073.4.12.vie.surfer.at 56 0.33
23 208.44.234.50=(not found) 56 0.33
65.55.209.159=msnbot-65-55-209-159.search.msn.
24 56 0.33
com
25 81.52.143.26=natcrawlbloc05.net.m1.fti.net 55 0.32
Sum 17,177 100.00

To top of page

Top 25 of 137 countries of origin , sorted by number of files

N countries of origin times %


1 net 103,051 26.55
2 Germany 82,261 21.20
3 (unresolved) 75,329 19.41
4 com 26,160 6.74
5 Poland 9,964 2.57
6 Austria 8,360 2.15
7 Netherlands 4,788 1.23
8 Switzerland 4,564 1.18
9 Lithuania 4,456 1.15
10 Australia 3,827 0.99
11 Italy 3,448 0.89
12 Hungary 3,108 0.80
13 Czech Republic 2,948 0.76
14 India 2,858 0.74
15 Sweden 2,839 0.73
16 Canada 2,669 0.69
17 Mexico 2,640 0.68
18 edu 2,635 0.68
19 Brazil 2,557 0.66
20 Belgium 2,431 0.63
21 Russian Federation 2,296 0.59
22 Indonesia 2,253 0.58
23 Romania 2,057 0.53
24 Norway 2,035 0.52
25 Finland 1,915 0.49
Sum 388,072 100.00

To top of page

Top 25 of 242 pathes , sorted by number of files

N pathes times %
1 /common/ 133,706 34.45
2 /avr_gra/ 66,729 17.20
3 / 44,884 11.57
4 /avr_en/beginner/ 17,827 4.59
5 /avr_en/ 12,645 3.26
6 /avr_de/beginner/ 12,063 3.11
7 /avr_de/ 11,144 2.87
8 /avr_en/calc/ 7,790 2.01
9 /avr_de/fcount/ 6,065 1.56
10 /avr_de/rechnen/ 5,356 1.38
11 /avr_en/source/ 4,924 1.27
12 /avr_de/stepper/ 4,778 1.23
13 /avr_de/praesentation/ 4,676 1.20
14 /avr_en/keypad/ 4,627 1.19
15 /avr_de/quellen/ 3,886 1.00
16 /avr_en/signalgen/pics/ 3,811 0.98
17 /avr_en/stepper/ 3,115 0.80
18 /avr_de/keypad/ 2,962 0.76
19 /gavrasm/ 2,815 0.73
/avr_de/rechteckgen/
20 2,721 0.70
bilder/
21 /avr_de/zeitschleifen/ 2,091 0.54
22 /avr_de/interrupts/ 2,078 0.54
23 /weblox_de/ 1,749 0.45
24 /avr_en/signalgen/ 1,522 0.39
25 /akkuload/ 1,521 0.39
Sum 388,072 100.00

To top of page

Top 25 of 242 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 748,588 18.85
2 /avr_gra/ 527,033 13.27
3 /avr_de/intro/pdf/ 264,423 6.66
4 / 254,384 6.41
5 /avr_de/fcount/ 233,127 5.87
6 /avr_de/ 175,684 4.42
7 /avr_en/ 174,366 4.39
8 /avr_en/beginner/ 149,442 3.76
9 /avr_de/stepper/ 124,726 3.14
10 /avr_de/beginner/ 114,449 2.88
11 /avr_en/signalgen/pics/ 99,755 2.51
12 /avr_en/stepper/ 77,604 1.95
13 /gavrasm/v21/ 73,514 1.85
/avr_de/rechteckgen/
14 73,282 1.85
bilder/
15 /avr_en/calc/ 71,694 1.81
16 /common/ 63,687 1.60
17 /avr_de/rechnen/ 49,908 1.26
18 /avr_en/signalgen/ 48,519 1.22
19 /avr_de/rechteckgen/ 45,681 1.15
20 /weblox_de/ 40,344 1.02
21 /avr_de/intro/ppt/ 38,094 0.96
22 /akkuload/ 36,949 0.93
23 /privat/magloop/ 34,689 0.87
24 /avr_en/keypad/ 33,695 0.85
25 /weblox_en/ 26,626 0.67
Sum 3,970,505 100.00

To top of page

Top 25 of 2254 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 19,574 5.04
2 /avr_gra/RingLogo.jpg 10,622 2.74
3 /common/app.gif 8,686 2.24
/common/download.
4 8,686 2.24
gif
5 /common/akkuload.gif 8,684 2.24
/common/knowhow.
6 8,677 2.24
gif
7 /common/clock.gif 8,671 2.23
8 /common/example.gif 8,657 2.23
9 /common/gavrasm.gif 8,657 2.23
10 /common/calc.gif 8,657 2.23
/common/gavrasmw.
11 8,644 2.23
gif
12 /avr_gra/stk_lcd.jpg 8,643 2.23
13 /common/beginner.gif 8,642 2.23
14 /common/r2r.gif 8,641 2.23
15 /common/adc.gif 8,626 2.22
16 /common/keyb.gif 8,622 2.22
17 /common/hardware.gif 8,614 2.22
18 /index.html 6,082 1.57
19 /avr_en/index.html 5,423 1.40
20 /avr_2313.gif 4,809 1.24
21 /avr_de/index.html 4,786 1.23
22 /dg4fac.gif 4,668 1.20
23 /avr-asm-tutorial.gif 4,641 1.20
24 /avr_gra/2313.gif 4,277 1.10
25 /common/ints.gif 4,189 1.08
Sum 388,072 100.00

To top of page

Top 25 of 2254 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 235,601 5.93
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 141,534 3.56
3 /avr_en/index.html 111,681 2.81
4 /avr_de/index.html 107,011 2.70
5 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 95,403 2.40
6 /avr_2313.gif 82,565 2.08
/avr_de/praesentation/Teil_5b_Beispiel01_02.
7 81,878 2.06
pdf
8 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 78,620 1.98
9 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 74,673 1.88
10 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 60,208 1.52
11 /dg4fac.gif 49,538 1.25
12 /avr_de/fcount/dscf0004.jpg 46,136 1.16
13 /avr_en/signalgen/pics/rectgen_wiring.jpg 45,627 1.15
14 /avr_gra/pwm_simul.jpg 45,278 1.14
15 /avr_gra/r2r_hardware.jpg 44,629 1.12
16 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 41,880 1.05
17 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 41,631 1.05
18 /avr_de/fcount/dscf0005.jpg 39,995 1.01
19 /favicon.ico 38,354 0.97
20 /avr_de/fcount/dscf0001.jpg 37,909 0.95
21 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 34,822 0.88
22 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 34,074 0.86
23 /avr_gra/exp2313.gif 32,946 0.83
24 /index.html 31,981 0.81
25 /avr_de/stepper/stepper_v1.gif 30,687 0.77
Sum 3,970,505 100.00

To top of page

Top 25 of 692 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 6,082 7.03
2 /avr_en/index.html 5,423 6.27
3 /avr_de/index.html 4,786 5.53
4 /avr_en/beginner/index.html 3,188 3.69
5 /avr_en/beginner/LEFT.html 3,094 3.58
6 /avr_en/beginner/RIGHT.html 2,864 3.31
7 /avr_de/beginner/index.html 1,867 2.16
8 /avr_de/beginner/links.html 1,806 2.09
9 /avr_de/beginner/rechts.html 1,715 1.98
/avr_en/beginner/HARDWARE.
10 1,276 1.48
html
11 /avr_en/beginner/REGISTER.html 986 1.14
12 /avr_en/keypad/keyboard.html 958 1.11
13 /avr_en/beginner/JUMP.html 807 0.93
14 /avr_en/AVR_DAC.html 794 0.92
15 /avr_en/beginner/TOOLS.html 742 0.86
16 /avr_de/beginner/hardware.html 694 0.80
17 /avr_en/beginner/WHY.html 687 0.79
18 /avr_de/beginner/register.html 673 0.78
19 /avr_en/beginner/CALC.html 661 0.76
20 /avr_de/stepper/stepper.html 657 0.76
21 /avr_de/praesentation/index.html 656 0.76
22 /avr_en/signalgen/rectgen_m8.html 652 0.75
23 /avr_en/beginner/SRAM.html 651 0.75
24 /avr_en/AVR_ADC500.html 640 0.74
25 /avr_en/beginner/PORTS.html 637 0.74
Sum 86,504 100.00

To top of page

Top 25 of 692 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 111,681 11.35
2 /avr_de/index.html 107,011 10.87
3 /index.html 31,981 3.25
4 /gb_new.html 23,370 2.37
5 /avr_en/beginner/RIGHT.html 20,640 2.10
6 /avr_en/beginner/JUMP.html 19,624 1.99
7 /avr_en/keypad/keyboard.html 19,506 1.98
8 /avr_de/dcf77uhr.html 19,286 1.96
9 /avr_en/beginner/CALC.html 16,063 1.63
10 /avr_de/beginner/sprung.html 15,700 1.60
11 /avr_en/beginner/LEFT.html 12,943 1.32
12 /avr_de/beginner/rechnen.html 12,656 1.29
13 /avr_de/keypad/keyboard.html 12,499 1.27
14 /avr_en/signalgen/rectgen_m8.html 12,444 1.26
15 /avr_en/beginner/REGISTER.html 12,142 1.23
16 /avr_de/beginner/rechts.html 12,008 1.22
17 /avr_en/AVR_DAC.html 11,758 1.19
18 /avr_en/beginner/PDETAIL.html 10,931 1.11
/avr_en/beginner/COMMANDS.
19 10,908 1.11
html
20 /avr_de/avr_dac.html 10,188 1.04
/avr_de/rechteckgen/rectgen_m8.
21 9,887 1.00
html
22 /avr_en/AVR_ADC500.html 9,820 1.00
23 /avr_de/stepper/stepper.html 9,761 0.99
24 /avr_en/beginner/HARDWARE.html 9,333 0.95
25 /avr_de/beginner/commands.html 9,309 0.95
Sum 984,083 100.00

To top of page

Top 25 of 703 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 10,622 18.52
2 /avr_gra/stk_lcd.jpg 8,643 15.07
3 /avr_gra/8515.jpg 2,229 3.89
4 /avr_gra/avr_isp.jpg 1,767 3.08
5 /avr_gra/exp2313g.jpg 1,765 3.08
6 /avr_gra/exp_2313.jpg 1,730 3.02
7 /avr_gra/r2r_wave.jpg 1,328 2.32
8 /avr_gra/r2r_sawtooth.jpg 1,254 2.19
9 /avr_gra/r2r_hardware.jpg 1,238 2.16
10 /avr_gra/r2r_triangle.jpg 1,229 2.14
11 /avr_gra/r2r_sawtooth741.jpg 1,219 2.13
12 /avr_gra/r2r_sawtoothupperbound.jpg 1,213 2.11
13 /avr_gra/r2r_upperbound.jpg 1,207 2.10
14 /avr_gra/AT90S8515.jpg 988 1.72
15 /avr_gra/adc8conn.jpg 835 1.46
16 /avr_gra/pwm_simul.jpg 835 1.46
17 /avr_gra/apps.jpg 828 1.44
18 /avr_en/signalgen/pics/rectgen_280.jpg 802 1.40
19 /akkuload/dscf0030s.jpg 720 1.26
20 /avr_de/stepper/stepper_sm.jpg 679 1.18
21 /avr_de/stepper/kp4m4-001.jpg 630 1.10
22 /avr_de/stepper/supply.jpg 620 1.08
23 /avr_de/stepper/driver.jpg 612 1.07
/avr_en/signalgen/pics/rectgen_wiring.
24 591 1.03
jpg
25 /avr_de/praesentation/zuendtester.jpg 578 1.01
Sum 57,359 100.00

To top of page

Top 25 of 466 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 8,686 4.32
/common/download.
2 8,686 4.32
gif
3 /common/akkuload.gif 8,684 4.31
/common/knowhow.
4 8,677 4.31
gif
5 /common/clock.gif 8,671 4.31
6 /common/example.gif 8,657 4.30
7 /common/gavrasm.gif 8,657 4.30
8 /common/calc.gif 8,650 4.30
/common/gavrasmw.
9 8,644 4.29
gif
10 /common/beginner.gif 8,642 4.29
11 /common/r2r.gif 8,641 4.29
12 /common/adc.gif 8,626 4.29
13 /common/keyb.gif 8,622 4.28
14 /common/hardware.gif 8,614 4.28
15 /avr_2313.gif 4,809 2.39
16 /dg4fac.gif 4,668 2.32
17 /avr-asm-tutorial.gif 4,641 2.31
18 /avr_gra/2313.gif 4,277 2.12
19 /common/ints.gif 4,189 2.08
20 /common/delay.gif 4,180 2.08
21 /common/tn13.gif 4,171 2.07
22 /avr_gra/exp2313.gif 1,843 0.92
23 /avr_gra/avr_isp.gif 1,740 0.86
24 /avr_gra/isp10pin.gif 1,735 0.86
25 /avr_gra/isp6pin.gif 1,731 0.86
Sum 201,279 100.00

To top of page

Top 25 of 247 entry pages , sorted by number of files

N entry pages times %


1 /index.html 2,767 16.16
2 /avr_en/index.html 1,805 10.54
3 /avr_de/index.html 1,425 8.32
4 /avr_en/beginner/index.html 867 5.06
5 /avr_de/beginner/index.html 452 2.64
6 /avr_en/AVR_DAC.html 442 2.58
7 /avr_en/beginner/HARDWARE.html 378 2.21
8 /avr_de/avr_dac.html 333 1.94
9 /avr_de/stepper/stepper.html 322 1.88
10 /avr_de/fcount/fcount_m8.html 312 1.82
11 /avr_en/keypad/keyboard.html 297 1.73
12 /avr_de/keypad/keyboard.html 272 1.59
13 /avr_en/signalgen/rectgen_m8.html 253 1.48
14 /avr_en/AVR_ADC500.html 237 1.38
/avr_de/rechteckgen/rectgen_m8.
15 219 1.28
html
16 /gb_new.html 217 1.27
17 /avr_de/intro/index.html 184 1.07
18 /avr_en/stepper/stepper.html 181 1.06
19 /avr_de/rechnen/multiplikation.html 157 0.92
20 /avr_de/rechnen/konversion.html 157 0.92
21 /privat/stechlin/index.html 152 0.89
22 /avr_de/beginner/diraus.html 145 0.85
23 /avr_en/beginner/SRAM.html 143 0.83
24 /avr_de/beginner/hardware.html 142 0.83
25 /avr_en/calc/CONVERSION.html 140 0.82
Sum 17,127 100.00

To top of page

Top 25 of 313 cheat pages , sorted by number of files

N cheat pages times %


1 1,935 9.08
2 /index.html 1,783 8.37
3 /avr_en/index.html 1,531 7.18
4 /avr_de/index.html 1,270 5.96
5 /avr_en/beginner/RIGHT.html 500 2.35
6 /avr_en/AVR_DAC.html 492 2.31
7 /avr_en/beginner/HARDWARE.html 468 2.20
8 /avr_en/keypad/keyboard.html 414 1.94
9 /avr_de/avr_dac.html 354 1.66
10 /avr_de/stepper/stepper.html 333 1.56
11 /avr_de/keypad/keyboard.html 323 1.52
12 /avr_de/fcount/fcount_m8.html 305 1.43
13 /avr_de/beginner/rechts.html 277 1.30
14 /avr_en/AVR_ADC500.html 270 1.27
15 /avr_en/beginner/REGISTER.html 266 1.25
16 /avr_en/signalgen/rectgen_m8.html 248 1.16
17 /avr_en/beginner/JUMP.html 234 1.10
18 /avr_de/beginner/hardware.html 232 1.09
19 /avr_en/beginner/TOOLS.html 206 0.97
20 /gb_new.html 201 0.94
/avr_de/rechteckgen/rectgen_m8.
21 195 0.92
html
22 /avr_en/beginner/SRAM.html 195 0.92
23 /akkuload/de/index.html 190 0.89
24 /avr_de/beginner/werkzeuge.html 186 0.87
25 /avr_en/beginner/CALC.html 186 0.87
Sum 21,311 100.00

To top of page

Top 25 of 212 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 5,837 13.47
2 /avr_en/beginner/index.html 5,309 12.25
3 /avr_de/beginner/index.html 3,037 7.01
4 /avr_en/index.html 2,743 6.33
5 / 2,658 6.13
6 /avr_en/beginner/RIGHT.html 2,572 5.93
7 /avr_en/ 2,484 5.73
8 /avr_en/beginner/LEFT.html 1,765 4.07
9 /avr_de/beginner/rechts.html 1,586 3.66
10 /weblox_de/index.html 1,584 3.65
11 /avr_de/beginner/links.html 1,343 3.10
12 /sitemap_de.html 1,178 2.72
13 /sitemap_en.html 1,041 2.40
14 /index.html 689 1.59
15 /avr_de/apps.html 594 1.37
16 /avr_de/ 508 1.17
17 /avr_de/interrupts/index.html 490 1.13
18 /avr_en/calc/index.html 460 1.06
19 /avr_en/AVR_TUT.html 442 1.02
20 /weblox_en/index.html 425 0.98
21 /avr_de/zeitschleifen/index.html 419 0.97
22 /avr_de/avr_tut.html 412 0.95
23 /avr_en/APPS.html 279 0.64
/avr_en/signalgen/rectgen_m8.
24 278 0.64
html
25 /avr_de/rechnen/index.html 261 0.60
Sum 43,344 100.00

To top of page

Top 25 of 1019 external referrers , sorted by number of files

N external referrers times %


1 - 23,912 84.86
2 http://www.mikrocontroller.net/articles/AVR 171 0.61
3 http://www.webring.com/hub?ring=avr 145 0.51
4 http://de.wikipedia.org/wiki/R2R-Netzwerk 84 0.30
5 http://www.educypedia.be/electronics/avr.htm 76 0.27
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
6 75 0.27
ESC_by1_bz0_bs0.html
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 72 0.26
8 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 67 0.24
9 http://avr-asm.tripod.com/ 64 0.23
10 http://www.dg4fac.de/linksunten.html 63 0.22
11 http://www.dg4fac.de/rechtsunten.html 61 0.22
http://www.elektronik-kompendium.de/public/arnerossius/schaltungen/avr
12 57 0.20
/avrkurs.htm
13 http://www.mikrocontroller.net/articles/Linksammlung 56 0.20
14 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 53 0.19
15 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 46 0.16
16 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 46 0.16
17 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 43 0.15
http://electrons.psychogenic.com/modules/arms/art/3/
18 AVRGCCProgrammingG 40 0.14
uide.php
19 http://www.dg4fac.de/stechlin/index.html 39 0.14
20 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 36 0.13
21 http://mathcs.slu.edu/~fritts/csci305_306/links.html 36 0.13
22 http://www.attiny.com/avrlinks.htm 35 0.12
23 http://hamavr.info/avrinfo.html 35 0.12
24 http://circuit.lt/?section=sch&page=avr.isp.lpt 34 0.12
25 http://www.rowalt.de/mc/avr/linksd.htm 34 0.12
Sum 28,177 100.00

To top of page

Top 25 of 209 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 5,475 39.12
2 http://www.google.com 2,831 20.23
3 http://www.google.at 441 3.15
4 http://www.google.co.in 377 2.69
5 http://www.google.co.uk 280 2.00
6 http://www.google.com.au 267 1.91
7 http://www.google.pl 244 1.74
8 http://www.google.ch 238 1.70
9 http://www.google.ca 229 1.64
10 http://www.google.nl 194 1.39
11 http://www.google.se 165 1.18
12 http://www.google.fi 133 0.95
http://www.google.com.
13 118 0.84
mx
14 http://www.google.it 118 0.84
15 http://www.google.co.id 110 0.79
16 http://www.google.hu 108 0.77
17 http://www.google.ro 100 0.71
http://de.search.yahoo.
18 90 0.64
com
19 http://www.google.com.br 88 0.63
20 http://www.google.fr 87 0.62
21 http://www.google.co.th 87 0.62
22 http://www.google.be 84 0.60
23 http://search.live.com 81 0.58
24 http://www.google.ru 81 0.58
25 http://search.yahoo.com 79 0.56
Sum 13,994 100.00

To top of page

Top 25 of 8220 search strings , sorted by number of files

N search strings times %


1 avr tutorial 402 2.87
2 avr assembler 232 1.66
3 avr 181 1.29
4 avr programming 154 1.10
5 attiny13 135 0.96
6 assembler 129 0.92
7 avr assembly 82 0.59
8 assembler tutorial 78 0.56
9 avr asm 70 0.50
10 atmega8 65 0.46
avr assembler
11 64 0.46
tutorial
12 ATtiny13 63 0.45
assembler
13 63 0.45
commands
14 AVR 54 0.39
15 AVR tutorial 52 0.37
16 gavrasm 46 0.33
17 atmega tutorial 45 0.32
18 AVR programming 44 0.31
19 avr assembly tutorial 43 0.31
20 stk500 37 0.26
21 avr asm tutorial 36 0.26
22 assembler avr 32 0.23
23 Assembler 31 0.22
24 r2r 28 0.20
25 atmega8 tutorial 27 0.19
Sum 13,994 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 341,733 88.06
2 304 Not changed 35,942 9.26
3 206 Partial information 8,712 2.24

http://www.avr-asm-tutorial.net/weblox_en/2008m10.html (1 of 2)1/20/2009 8:07:21 PM


Weblog statistic for http://www.avr-asm-tutorial.net

4 301 Permanently moved 755 0.19


5 404 File not found 711 0.18
6 403 Forbidden 111 0.03
7 300 Multiple choices 94 0.02
8 405 Method not allowed 8 0.00
9 xxx Unknown error 6 0.00
Sum 388,072 100.00

To top of page

Top 25 of 273 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 160 22.50
2 /beginner_de.pdf 77 10.83
3 /com/img/translation/t.gif 27 3.80
4 /_vti_inf.html 18 2.53
5 /avr_de/intro/ppt/beispiel10_snd.wav 12 1.69
6 /avr_de/praesentation/favicon.ico 11 1.55
7 /avr_de/praesentation/favicon.gif 11 1.55
/_vti_bin/owssvr.dll?
8 8 1.13
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
9 8 1.13
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
10 20la 7 0.98
nguage_files/LEFT.htm
11 /avr_en/beginner/index.html/url%5d 6 0.84
/_vti_bin/owssvr.dll?
12 6 0.84
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 6 0.84
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
14 /avr_de/rechnen/8515.jpg 6 0.84
/avr_en/calc/CONVERT.html/routines/fieldValidation.php?jssShopFileSyst
15 5 0.70
em=http://www.codeduc.cl/components/id.txt????
/avr_en/calc/routines/fieldValidation.php?jssShopFileSystem=http://www
16 5 0.70
.codeduc.cl/components/id.txt????
/routines/fieldValidation.php?jssShopFileSystem=http://www.codeduc.cl/
17 5 0.70
components/id.txt????
18 /avr_en/r2r.gif 4 0.56
19 /avr_de/rechteckgen/rectgen_280.jpg 4 0.56
//decoder/markdown.php?ccms_library_path=http://www.voltaique.com/admi
20 4 0.56
nistrator/components/com_login/id.txt???
21 /avr_de/beginner/portdetail.html 4 0.56
22 /avr_gra/r2r_sine.jpg 3 0.42
23 /cnt 3 0.42
24 /avr_en/stk_lcd.jpg 3 0.42
25 /avr_en/example.gif 3 0.42
Sum 711 100.00

To top of page

Top 25 of 215 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 203,739 52.50
2 Mozilla/4.0 149,037 38.40
3 Opera/9.52 4,691 1.21
4 Opera/9.60 4,671 1.20
5 Mozilla/4.5 2,710 0.70
6 Opera/9.51 2,366 0.61
7 Yanga 2,001 0.52
8 Opera/9.50 1,844 0.48
9 msnbot/1.1 1,812 0.47
10 Opera/9.27 1,316 0.34
11 Opera/9.61 1,195 0.31
12 yacybot 1,081 0.28
Googlebot-
13 971 0.25
Image/1.0
14 Opera/9.25 920 0.24
15 Yandex/1.01.001 689 0.18
16 Teleport 620 0.16
17 Opera/9.26 587 0.15
18 msnbot-media/1.1 565 0.15
19 msnbot-media/1.0 526 0.14
20 Opera/9.23 500 0.13
21 ichiro/3.0 489 0.13
22 - 451 0.12
23 Opera/9.21 396 0.10
24 Eurobot/1.0 386 0.10
25 Ocelli/1.4 385 0.10
Sum 388,072 100.00

To top of page

Top 25 of 508 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.3 101,301 26.10
2 MSIE 7.0 71,180 18.34
3 MSIE 6.0 65,997 17.01
4 Firefox/2.0.0.17 22,243 5.73
5 Firefox/3.0.1 13,446 3.46
6 Gecko 9,996 2.58
7 Firefox/3.0.3 6,564 1.69
8 unknown 6,139 1.58
9 Slurp 6,057 1.56
10 Opera/9.60 4,655 1.20
11 Opera/9.52 4,598 1.18
12 Firefox/3.0 3,998 1.03
13 Firefox/2.0.0.16 3,364 0.87
14 FDM 2,873 0.74
15 HTTrack 3.0x 2,686 0.69
16 Firefox/2.0.0.14 2,366 0.61
17 MSIE 5.0 2,352 0.61
18 Opera/9.51 2,347 0.60
19 Firefox/3.0.2 2,149 0.55
20 Googlebot/2.1 1,995 0.51
21 Opera/9.50 1,815 0.47
22 msnbot/1.1 1,812 0.47
23 Firefox/2.0.0.6 1,660 0.43
24 Slurp/3.0 1,621 0.42
25 Firefox/2.0.0.11 1,460 0.38
Sum 388,072 100.00

To top of page

Top 25 of 77 operating systems , sorted by number of files

N operating systems times %


1 Windows 155,057 39.96
2 Windows NT 5.1 129,536 33.38
3 unknown 26,529 6.84
4 Linux i686 23,342 6.01
5 Windows NT 6.0 20,287 5.23
6 Windows NT 5.0 8,897 2.29
7 Windows 98 4,596 1.18
8 Linux x86_64 3,889 1.00
9 Mac OS X 10.5 1,885 0.49
10 Mac OS X 10_5_5 1,804 0.46
11 Windows NT 4.0 1,713 0.44
12 Windows XP 5.1 1,654 0.43
13 Windows NT 5.2 1,572 0.41
14 Mac OS X 1,330 0.34
15 Linux 1,218 0.31
Mac OS X
16 880 0.23
10_4_11
17 Win16 697 0.18
18 Mac OS X 10.4 637 0.16
19 Linux i686 383 0.10
20 Mac OS X 10_5_4 370 0.10
21 Windows 6.0 183 0.05
22 Mac OS X Mach-O 167 0.04
23 SunOS sun4u 144 0.04
24 Kubuntu 131 0.03
25 Windows CE 119 0.03
Sum 388,072 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 10,926 2.82
2 01 7,660 1.97
3 02 6,859 1.77
4 03 5,363 1.38
5 04 6,010 1.55
6 05 6,749 1.74
7 06 7,700 1.98
8 07 9,433 2.43
9 08 13,357 3.44
10 09 18,758 4.83
11 10 18,313 4.72
12 11 20,698 5.33
13 12 21,255 5.48
14 13 21,414 5.52
15 14 21,876 5.64
16 15 22,357 5.76
17 16 20,443 5.27
18 17 20,316 5.24
19 18 21,272 5.48
20 19 21,397 5.51
21 20 25,317 6.52
22 21 25,418 6.55
23 22 20,433 5.27
24 23 14,748 3.80
Sum 388,072 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008m10.html (2 of 2)1/20/2009 8:07:21 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w53

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 53

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 2169 IPs and host names , sorted by number of files

N IPs and host names times %


1 85.178.210.56=e178210056.adsl.alicedsl.de 1,485 4.10
2 210.173.180.155=(not found) 347 0.96
3 93.135.158.200=pass-5d879ec8.pool.einsundeins.de 326 0.90
4 218.248.69.7=(not found) 301 0.83
5 78.46.86.53=crawl1.hetzner.itroot.de 273 0.75
6 41.208.50.160=gprs01.rb.mtnns.net 241 0.66
7 67.195.37.111=llf320022.crawl.yahoo.net 228 0.63
8 202.70.55.9=(not found) 227 0.63
9 80.143.214.213=p508FD6D5.dip.t-dialin.net 220 0.61
10 79.196.86.143=p4FC4568F.dip.t-dialin.net 213 0.59
11 91.205.124.9=(not found) 211 0.58
12 189.175.176.226=dsl-189-175-176-226.prod-infinitum.com.mx 208 0.57
13 118.68.189.142=adsl-dynamic-pool-xxx.hcm.fpt.vn 204 0.56
14 91.177.223.178=178.223-177-91.adsl-dyn.isp.belgacom.be 198 0.55
15 213.196.207.236=xdsl-213-196-207-236.netcologne.de 188 0.52
16 86.87.31.219=ip56571fdb.direct-adsl.nl 179 0.49
85.225.114.33=c-2172e155.138-2-64736c10.cust.bredbandsbolaget.
17 161 0.44
se
18 90.231.214.197=90-231-214-197-no124.tbcn.telia.com 154 0.42
19 87.4.167.221=host221-167-dynamic.4-87-r.retail.telecomitalia.it 130 0.36
20 217.233.74.117=pD9E94A75.dip.t-dialin.net 130 0.36
21 67.139.41.162=(not found) 127 0.35
22 88.134.112.162=88-134-112-162-dynip.superkabel.de 108 0.30
23 85.204.216.98=(not found) 105 0.29
24 79.196.107.104=p4FC46B68.dip.t-dialin.net 105 0.29
25 84.188.78.133=p54BC4E85.dip.t-dialin.net 104 0.29
Sum 36,255 100.00

To top of page

Top 25 of 2169 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 85.178.210.56=e178210056.adsl.alicedsl.de 38,494 8.49
2 79.217.210.140=p4FD9D28C.dip.t-dialin.net 22,367 4.93
3 91.205.124.9=(not found) 14,686 3.24
4 80.120.130.73=(not found) 9,966 2.20
5 89.207.248.89=tum-party-visitors.vipri.net 5,115 1.13
6 91.38.161.12=p5B26A10C.dip0.t-ipconnect.de 5,094 1.12
7 85.179.42.145=e179042145.adsl.alicedsl.de 4,990 1.10
8 88.116.71.250=(not found) 4,544 1.00
213.196.207.236=xdsl-213-196-207-236.netcologne.
9 4,454 0.98
de
10 210.173.180.155=(not found) 4,451 0.98
11 77.4.213.102=mnch-4d04d566.pool.mediaWays.net 4,425 0.98
12 77.22.115.197=(not found) 3,998 0.88
13 62.153.101.26=(not found) 3,871 0.85
14 87.171.241.249=p57ABF1F9.dip.t-dialin.net 3,655 0.81
15 93.128.229.94=erft-5d80e55e.pool.einsundeins.de 3,392 0.75
16 89.52.129.159=P819f.p.pppool.de 3,381 0.75
17 80.143.203.105=p508FCB69.dip.t-dialin.net 3,258 0.72
18 41.208.50.160=gprs01.rb.mtnns.net 3,093 0.68
19 78.46.86.53=crawl1.hetzner.itroot.de 3,023 0.67
20 202.70.55.9=(not found) 3,002 0.66
21 84.157.116.242=p549D74F2.dip.t-dialin.net 2,911 0.64
22 79.196.86.143=p4FC4568F.dip.t-dialin.net 2,857 0.63
23 82.149.180.109=xdsly109.osnanet.de 2,645 0.58
24 67.195.37.111=llf320022.crawl.yahoo.net 2,589 0.57
25 79.199.242.20=p4FC7F214.dip.t-dialin.net 2,545 0.56
Sum 453,518 100.00

To top of page

Top 25 of 341 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.111=llf320022.crawl.yahoo.net 52 4.18
2 66.249.71.206=crawl-66-249-71-206.googlebot.com 41 3.29
3 66.249.71.205=crawl-66-249-71-205.googlebot.com 37 2.97
4 66.249.71.207=crawl-66-249-71-207.googlebot.com 32 2.57
5 74.6.18.222=llf520144.crawl.yahoo.net 22 1.77
6 78.46.86.53=crawl1.hetzner.itroot.de 20 1.61
7 193.252.149.15=natcrawlbloc02.net.s1.fti.net 20 1.61
8 212.143.177.197=(not found) 20 1.61
9 74.6.22.189=llf520043.crawl.yahoo.net 17 1.37
10 72.30.87.112=llf531192.crawl.yahoo.net 17 1.37
11 81.52.143.16=natcrawlbloc03.net.m1.fti.net 17 1.37
12 74.6.22.187=llf520053.crawl.yahoo.net 16 1.29
13 58.239.73.120=(not found) 15 1.20
14 81.52.143.15=natcrawlbloc01.net.m1.fti.net 14 1.12
15 193.47.80.44=crawl8.exabot.com 13 1.04
16 81.52.143.26=natcrawlbloc05.net.m1.fti.net 12 0.96
17 67.195.37.176=llf320072.crawl.yahoo.net 11 0.88
18 93.135.158.200=pass-5d879ec8.pool.einsundeins.de 9 0.72
88.104.236.124=88-104-236-124.dynamic.dsl.as9105.
19 9 0.72
com
20 123.118.12.12=(not found) 9 0.72
21 65.55.212.136=(not found) 8 0.64
22 72.36.115.86=cazoodle115-86.cazoodle.com 8 0.64
23 88.131.106.16=(not found) 8 0.64
24 118.136.59.85=85.59.136.118.fast.net.id 8 0.64
25 66.235.124.3=crawler5003.ask.com 7 0.56
Sum 1,245 100.00

To top of page

Top 25 of 77 countries of origin , sorted by number of files

N countries of origin times %


1 net 11,386 31.41
2 Germany 8,385 23.13
3 (unresolved) 6,121 16.88
4 com 2,204 6.08
5 Poland 1,007 2.78
6 Austria 658 1.81
7 Switzerland 643 1.77
8 Netherlands 511 1.41
9 Italy 509 1.40
10 Belgium 492 1.36
11 Mexico 390 1.08
12 Sweden 327 0.90
13 Russian Federation 265 0.73
14 Indonesia 245 0.68
15 Australia 234 0.65
16 Vietnam 222 0.61
17 India 197 0.54
18 Hungary 159 0.44
19 Czech Republic 151 0.42
20 Greece 144 0.40
21 Lithuania 139 0.38
22 Slovak Republic 138 0.38
23 Canada 131 0.36
24 France 113 0.31
25 Brazil 109 0.30
Sum 36,255 100.00

To top of page

Top 25 of 118 pathes , sorted by number of files

N pathes times %
1 /common/ 12,791 35.28
2 /avr_gra/ 5,797 15.99
3 / 4,306 11.88
4 /avr_en/beginner/ 1,450 4.00
5 /avr_en/ 1,137 3.14
6 /avr_de/ 1,089 3.00
7 /avr_de/beginner/ 1,044 2.88
8 /avr_en/source/ 628 1.73
9 /avr_en/calc/ 574 1.58
10 /avr_de/rechnen/ 573 1.58
11 /avr_de/fcount/ 532 1.47
12 /avr_de/stepper/ 499 1.38
13 /avr_de/praesentation/ 452 1.25
14 /avr_de/quellen/ 440 1.21
15 /gavrasm/ 330 0.91
16 /avr_en/keypad/ 329 0.91
17 /avr_en/stepper/ 292 0.81
18 /avr_de/rechteckgen/bilder/ 278 0.77
19 /avr_de/keypad/ 250 0.69
20 /avr_en/signalgen/pics/ 248 0.68
21 /avr_de/zeitschleifen/ 195 0.54
22 /avr_de/interrupts/ 167 0.46
23 /gavrasm/v22/ 162 0.45
/privat/Weihnachten2008/
24 162 0.45
thumbs/
25 /privat/magloop/ 146 0.40
Sum 36,255 100.00

To top of page

Top 25 of 118 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 82,696 18.23
2 /avr_de/intro/pdf/ 67,686 14.92
3 /avr_gra/ 43,399 9.57
4 / 24,970 5.51
5 /avr_de/fcount/ 20,125 4.44
6 /gavrasm/v22/ 19,015 4.19
7 /avr_de/ 17,502 3.86
8 /avr_en/ 16,393 3.61
9 /avr_en/beginner/ 12,323 2.72
10 /avr_de/stepper/ 12,096 2.67
11 /avr_de/beginner/ 9,713 2.14
12 /avr_en/stepper/ 8,004 1.76
13 /avr_de/rechteckgen/ 7,837 1.73
14 /privat/magloop/ 7,293 1.61
/avr_de/rechteckgen/
15 7,257 1.60
bilder/
16 /avr_en/signalgen/pics/ 6,990 1.54
17 /weblox_de/ 6,955 1.53
18 /weblox_en/ 6,776 1.49
19 /common/ 6,196 1.37
20 /avr_en/calc/ 6,019 1.33
21 /avr_en/signalgen/ 6,014 1.33
22 /avr_de/rechnen/ 5,340 1.18
23 /avr_de/intro/ppt/ 5,043 1.11
24 /privat/Weihnachten2008/ 3,368 0.74
25 /avr_en/source/ 3,118 0.69
Sum 453,518 100.00

To top of page

Top 25 of 1256 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 1,848 5.10
2 /avr_gra/RingLogo.jpg 1,026 2.83
3 /common/clock.gif 837 2.31
4 /common/calc.gif 833 2.30
/common/knowhow.
5 832 2.29
gif
6 /common/app.gif 830 2.29
7 /common/keyb.gif 829 2.29
8 /common/r2r.gif 829 2.29
9 /common/akkuload.gif 828 2.28
/common/download.
10 828 2.28
gif
11 /common/gavrasm.gif 828 2.28
12 /common/hardware.gif 827 2.28
13 /common/adc.gif 826 2.28
/common/gavrasmw.
14 825 2.28
gif
15 /common/example.gif 824 2.27
16 /common/beginner.gif 823 2.27
17 /avr_gra/stk_lcd.jpg 821 2.26
18 /index.html 627 1.73
19 /avr_en/index.html 535 1.48
20 /avr_2313.gif 460 1.27
21 /avr_de/index.html 459 1.27
22 /dg4fac.gif 458 1.26
23 /avr-asm-tutorial.gif 454 1.25
24 /common/delay.gif 399 1.10
25 /common/ints.gif 398 1.10
Sum 36,255 100.00

To top of page

Top 25 of 1256 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 34,887 7.69
2 /avr_de/praesentation/Anwendungsbeispiele.pdf 23,952 5.28
3 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 18,915 4.17
4 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 13,531 2.98
/avr_de/praesentation/Teil_5b_Beispiel01_02.
5 11,498 2.54
pdf
6 /avr_en/index.html 11,251 2.48
7 /avr_de/index.html 10,854 2.39
8 /avr_2313.gif 8,103 1.79
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 7,954 1.75
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 6,869 1.51
11 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 6,235 1.37
12 /avr_de/rechteckgen/rectgen_m8.xls 5,822 1.28
13 /avr_de/intro/pdf/Teil1_Prozessor.pdf 5,767 1.27
14 /dg4fac.gif 4,838 1.07
15 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 4,450 0.98
16 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 4,365 0.96
17 /avr_gra/pwm_simul.jpg 4,130 0.91
18 /avr_de/fcount/dscf0004.jpg 3,886 0.86
19 /favicon.ico 3,630 0.80
20 /avr_en/signalgen/rectgen_m8.xls 3,531 0.78
21 /gavrasm/v22/gavrasm_win_en_22.zip 3,415 0.75
22 /index.html 3,402 0.75
23 /avr_de/fcount/dscf0005.jpg 3,389 0.75
24 /gavrasm/v22/gavrasm_win_de_22.zip 3,339 0.74
25 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 3,276 0.72
Sum 453,518 100.00

To top of page

Top 25 of 439 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 627 7.97
2 /avr_en/index.html 535 6.80
3 /avr_de/index.html 459 5.84
4 /avr_en/beginner/index.html 258 3.28
5 /avr_en/beginner/RIGHT.html 233 2.96
6 /avr_en/beginner/LEFT.html 232 2.95
7 /avr_de/beginner/index.html 167 2.12
8 /avr_de/beginner/rechts.html 160 2.03
9 /avr_de/beginner/links.html 156 1.98
/avr_en/beginner/HARDWARE.
10 88 1.12
html
11 /avr_en/beginner/REGISTER.html 84 1.07
12 /avr_en/beginner/JUMP.html 81 1.03
13 /avr_de/beginner/hardware.html 80 1.02
14 /avr_en/keypad/keyboard.html 80 1.02
15 /avr_de/stepper/stepper.html 70 0.89
16 /avr_de/apps.html 68 0.86
17 /sitemap_de.html 63 0.80
18 /gavrasm/index_en.html 63 0.80
19 /gavrasm/index_de.html 62 0.79
20 /avr_en/beginner/SRAM.html 61 0.78
21 /avr_en/beginner/CALC.html 60 0.76
22 /avr_en/AVR_DAC.html 59 0.75
23 /avr_de/praesentation/index.html 59 0.75
24 /avr_de/keypad/keyboard.html 59 0.75
25 /akkuload/de/index.html 58 0.74
Sum 7,866 100.00

To top of page

Top 25 of 439 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 11,251 11.51
2 /avr_de/index.html 10,854 11.10
3 /index.html 3,402 3.48
4 /avr_de/dcf77uhr.html 2,025 2.07
5 /avr_en/beginner/JUMP.html 1,872 1.91
6 /gb_new.html 1,836 1.88
7 /avr_en/keypad/keyboard.html 1,672 1.71
8 /avr_en/beginner/RIGHT.html 1,592 1.63
9 /avr_en/beginner/CALC.html 1,470 1.50
10 /avr_de/beginner/sprung.html 1,364 1.39
11 /avr_de/beginner/rechts.html 1,112 1.14
12 /avr_de/beginner/rechnen.html 1,107 1.13
13 /avr_en/beginner/LEFT.html 1,040 1.06
14 /avr_en/beginner/REGISTER.html 1,040 1.06
15 /sitemap_de.html 1,040 1.06
16 /avr_de/beginner/pdetail.html 1,008 1.03
17 /avr_de/keypad/keyboard.html 1,007 1.03
/avr_de/rechteckgen/rectgen_m8.
18 946 0.97
html
19 /avr_de/stepper/stepper.html 944 0.97
/avr_en/beginner/COMMANDS.
20 938 0.96
html
21 /avr_en/signalgen/rectgen_m8.html 882 0.90
22 /avr_de/beginner/commands.html 792 0.81
23 /avr_en/AVR_DAC.html 788 0.81
24 /avr_de/avr_dac.html 756 0.77
25 /avr_en/AVR_ADC500.html 731 0.75
Sum 97,782 100.00

To top of page

Top 25 of 301 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 1,023 19.83
2 /avr_gra/stk_lcd.jpg 821 15.92
3 /avr_gra/avr_isp.jpg 154 2.99
4 /avr_gra/exp2313g.jpg 152 2.95
5 /avr_gra/exp_2313.jpg 152 2.95
6 /avr_gra/8515.jpg 131 2.54
7 /avr_gra/r2r_wave.jpg 107 2.07
8 /avr_gra/r2r_sawtooth.jpg 90 1.74
9 /avr_gra/AT90S8515.jpg 89 1.73
10 /avr_gra/apps.jpg 89 1.73
11 /avr_gra/r2r_triangle.jpg 87 1.69
12 /avr_gra/r2r_sawtoothupperbound.jpg 87 1.69
13 /avr_gra/r2r_sawtooth741.jpg 87 1.69
14 /avr_gra/r2r_hardware.jpg 87 1.69
15 /avr_gra/r2r_upperbound.jpg 86 1.67
16 /avr_gra/adc8conn.jpg 74 1.43
17 /avr_gra/pwm_simul.jpg 73 1.42
18 /avr_de/stepper/stepper_sm.jpg 70 1.36
19 /avr_de/stepper/driver.jpg 63 1.22
20 /avr_de/stepper/supply.jpg 63 1.22
21 /avr_de/stepper/kp4m4-001.jpg 63 1.22
22 /akkuload/dscf0030s.jpg 62 1.20
/avr_de/rechteckgen/bilder/rectgen_280.
23 58 1.12
jpg
24 /avr_en/signalgen/pics/rectgen_280.jpg 55 1.07
25 /avr_de/praesentation/zuendtester.jpg 51 0.99
Sum 5,158 100.00

To top of page

Top 25 of 236 GIF-files , sorted by number of files

N GIF-files times %
1 /common/clock.gif 837 4.46
2 /common/calc.gif 833 4.44
/common/knowhow.
3 832 4.44
gif
4 /common/app.gif 830 4.43
5 /common/keyb.gif 829 4.42
6 /common/r2r.gif 829 4.42
7 /common/akkuload.gif 828 4.42
/common/download.
8 828 4.42
gif
9 /common/gavrasm.gif 828 4.42
10 /common/hardware.gif 827 4.41
11 /common/adc.gif 826 4.41
/common/gavrasmw.
12 825 4.40
gif
13 /common/example.gif 824 4.39
14 /common/beginner.gif 823 4.39
15 /avr_2313.gif 459 2.45
16 /dg4fac.gif 458 2.44
17 /avr-asm-tutorial.gif 454 2.42
18 /common/delay.gif 399 2.13
19 /common/ints.gif 398 2.12
20 /common/tn13.gif 394 2.10
21 /avr_gra/2313.gif 374 1.99
22 /avr_gra/exp2313.gif 171 0.91
23 /avr_gra/avr_isp.gif 156 0.83
24 /avr_gra/isp6pin.gif 153 0.82
25 /avr_gra/isp10pin.gif 151 0.81
Sum 18,750 100.00

To top of page

Top 25 of 138 entry pages , sorted by number of files

N entry pages times %


1 /index.html 298 18.24
2 /avr_en/index.html 208 12.73
3 /avr_de/index.html 156 9.55
4 /avr_en/beginner/index.html 76 4.65
5 /avr_de/beginner/index.html 40 2.45
6 /avr_de/stepper/stepper.html 39 2.39
7 /avr_en/AVR_DAC.html 31 1.90
8 /avr_de/fcount/fcount_m8.html 28 1.71
9 /avr_en/keypad/keyboard.html 27 1.65
/avr_de/rechteckgen/rectgen_m8.
10 26 1.59
html
11 /avr_en/beginner/HARDWARE.html 25 1.53
12 /avr_de/avr_dac.html 24 1.47
13 /avr_de/intro/index.html 24 1.47
14 /avr_en/stepper/stepper.html 23 1.41
15 /avr_en/signalgen/rectgen_m8.html 23 1.41
16 /avr_de/keypad/keyboard.html 19 1.16
17 /avr_de/rechnen/konversion.html 17 1.04
18 /avr_en/AVR_ADC500.html 17 1.04
19 /avr_en/beginner/JUMP.html 16 0.98
20 /avr_de/beginner/hardware.html 16 0.98
21 /avr_en/beginner/REGISTER.html 15 0.92
22 /avr_de/beginner/pdetail.html 14 0.86
23 /gavrasm/index_en.html 13 0.80
24 /avr_en/beginner/CALC.html 13 0.80
25 /gb_new.html 13 0.80
Sum 1,634 100.00

To top of page

Top 25 of 171 cheat pages , sorted by number of files

N cheat pages times %


1 336 15.49
2 /index.html 199 9.17
3 /avr_en/index.html 158 7.28
4 /avr_de/index.html 148 6.82
5 /avr_en/beginner/RIGHT.html 52 2.40
6 /avr_en/beginner/HARDWARE.html 38 1.75
7 /avr_en/keypad/keyboard.html 35 1.61
8 /avr_de/stepper/stepper.html 33 1.52
9 /avr_en/AVR_DAC.html 32 1.48
10 /avr_en/beginner/JUMP.html 29 1.34
11 /avr_de/intro/index.html 28 1.29
12 /avr_de/avr_dac.html 27 1.24
13 /avr_de/beginner/rechts.html 27 1.24
14 /avr_de/beginner/rechnen.html 26 1.20
15 /avr_de/fcount/fcount_m8.html 25 1.15
16 /avr_en/beginner/REGISTER.html 24 1.11
17 /avr_en/stepper/stepper.html 23 1.06
18 /gavrasm/index_en.html 21 0.97
19 /avr_de/beginner/hardware.html 21 0.97
20 /avr_en/beginner/CALC.html 21 0.97
21 /avr_de/keypad/keyboard.html 21 0.97
22 /avr_en/beginner/SRAM.html 21 0.97
/avr_de/rechteckgen/rectgen_m8.
23 21 0.97
html
24 /akkuload/de/index.html 19 0.88
25 /avr_de/beginner/werkzeuge.html 19 0.88
Sum 2,169 100.00

To top of page

Top 25 of 127 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 705 17.07
2 / 577 13.97
3 /avr_en/beginner/index.html 406 9.83
4 /avr_en/ 351 8.50
5 /avr_de/beginner/index.html 271 6.56
6 /avr_en/index.html 256 6.20
7 /avr_en/beginner/RIGHT.html 199 4.82
8 /avr_en/beginner/LEFT.html 181 4.38
9 /avr_de/beginner/rechts.html 133 3.22
10 /avr_de/apps.html 96 2.32
11 /avr_de/beginner/links.html 94 2.28
12 /avr_de/interrupts/index.html 44 1.07
13 /avr_en/calc/index.html 44 1.07
14 /sitemap_de.html 41 0.99
15 /index.html 40 0.97
16 /avr_de/zeitschleifen/index.html 40 0.97
17 /avr_en/AVR_TUT.html 36 0.87
18 /avr_en/APPS.html 32 0.77
19 /avr_de/ 31 0.75
20 /avr_de/avr_tut.html 21 0.51
/avr_en/beginner/COMMANDS.
21 21 0.51
html
22 /avr_en/signalgen/rectgen_m8.html 19 0.46
23 /avr_en/AVR_HARD.html 19 0.46
24 /sitemap_en.html 19 0.46
25 /avr_de/rechnen/index.html 18 0.44
Sum 4,130 100.00

To top of page

Top 25 of 200 external referrers , sorted by number of files

N external referrers times %


1 - 2,150 84.75
2 http://www.webring.com/hub?ring=avr 23 0.91
3 http://www.mikrocontroller.net/articles/AVR 18 0.71
4 http://www.dg4fac.de/linksunten.html 11 0.43
5 9 0.35
6 http://avr-asm.tripod.com/ 8 0.32
7 http://www.rowalt.de/mc/avr/linksd.htm 8 0.32
http://electrons.psychogenic.com/modules/arms/art/3/
8 AVRGCCProgrammingG 7 0.28
uide.php
9 http://www.asurowiki.de/pmwiki/pmwiki.php/Main/Assembler 6 0.24
10 http://www.educypedia.be/electronics/avr.htm 6 0.24
11 http://members.ziggo.nl/electro1/avr/avrlinks.htm 6 0.24
12 http://www.attiny.com/avrlinks.htm 5 0.20
13 http://www.bigmike.it/ircontrol/ 5 0.20
14 http://de.wikipedia.org/wiki/R2R-Netzwerk 5 0.20
15 http://www.mikrocontroller.net/articles/Linksammlung 5 0.20
16 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 5 0.20
17 http://it.wikipedia.org/wiki/Atmel_AVR 5 0.20
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
18 5 0.20
ESC_by1_bz0_bs0.html
19 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 5 0.20
20 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 4 0.16
21 http://www.nntp.it/hobby-elettronica/104850-guida-atmel.html 4 0.16
22 http://www.serasidis.gr/link.htm 4 0.16
23 http://www.elektroda.pl/rtvforum/topic404420.html 4 0.16
24 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 4 0.16
25 http://www.dg4fac.de/rechtsunten.html 4 0.16
Sum 2,537 100.00

To top of page

Top 25 of 87 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 454 40.64
2 http://www.google.com 251 22.47
3 http://www.google.at 35 3.13
4 http://www.google.co.in 30 2.69
5 http://www.google.ca 19 1.70
6 http://www.google.pl 18 1.61
7 http://www.google.ch 17 1.52
8 http://www.google.co.uk 14 1.25
9 http://www.google.se 13 1.16
10 http://www.google.hu 12 1.07
11 http://www.google.fr 11 0.98
12 http://www.google.nl 10 0.90
13 http://suche.t-online.de 10 0.90
14 http://www.google.co.id 10 0.90
15 http://www.google.com.vn 9 0.81
16 http://www.google.fi 9 0.81
17 http://www.google.com.au 8 0.72
18 http://www.google.it 7 0.63
http://de.search.yahoo.
19 7 0.63
com
20 http://www.google.com.pk 7 0.63
21 http://www.google.be 7 0.63
22 http://www.google.cz 7 0.63
23 http://www.google.co.nz 6 0.54
24 http://search.yahoo.com 6 0.54
http://www.google.com.
25 6 0.54
mx
Sum 1,117 100.00

To top of page

Top 25 of 837 search strings , sorted by number of files

N search strings times %


1 avr tutorial 33 2.95
2 avr assembler 19 1.70
3 avr 16 1.43
4 avr asm 14 1.25
5 attiny13 13 1.16
6 avr asm tutorial 10 0.90
7 assembler 9 0.81
8 avr assembly tutorial 7 0.63
9 avr assembly 7 0.63
10 atmega8 6 0.54
11 avr programming 6 0.54
12 avr assembler tutorial 6 0.54
13 AVR 6 0.54
14 AVR-ASM-tutorial 6 0.54
15 Assembler 4 0.36
16 AVR tutorial 4 0.36
17 assembler tutorial 4 0.36
18 wavrasm 4 0.36
19 avr tutorial pdf 4 0.36
20 ATtiny13 4 0.36
AVR assembly source
21 4 0.36
code
22 avr registers 3 0.27
23 avr tastatur 3 0.27
24 programming avr 3 0.27
25 avr-asm tutorial 3 0.27
Sum 1,117 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 32,331 89.18
2 304 Not changed 3,383 9.33
3 206 Partial information 261 0.72
4 301 Permanently moved 130 0.36
5 404 File not found 70 0.19
6 405 Method not allowed 63 0.17
7 403 Forbidden 9 0.02
8 300 Multiple choices 5 0.01
9 400 Error in request 3 0.01

http://www.avr-asm-tutorial.net/weblox_en/2008w53.html (1 of 2)1/20/2009 8:07:41 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Sum 36,255 100.00

To top of page

Top 25 of 27 files not found , sorted by number of files

N files not found times %


1 /beginner_de.pdf 26 37.14
2 /beginner_en.pdf 13 18.57
/_vti_bin/owssvr.dll?
3 4 5.71
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
4 4 5.71
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
5 20la 1 1.43
nguage_files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
6 20la 1 1.43
nguage_files/RIGHT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
7 20la 1 1.43
nguage8_files/LEFT.htm
8 /gavrasm/v16/LiesMich.Txt 1 1.43
9 /avr_de/keypad/gb_new.html 1 1.43
10 /keypad/gb_new.html 1 1.43
11 /roundcubemail-0.1/bin/msgimport 1 1.43
12 /roundcubemail/bin/msgimport 1 1.43
13 /roundcubemail-0.2/bin/msgimport 1 1.43
14 /roundcube-0.1/bin/msgimport 1 1.43
15 /webmail/bin/msgimport 1 1.43
16 /mail/bin/msgimport 1 1.43
17 /bin/msgimport 1 1.43
18 /roundcube/bin/msgimport 1 1.43
19 /rc/bin/msgimport 1 1.43
20 /twiki/bin/configure?action=image 1 1.43
21 /wiki/bin/configure?action=image 1 1.43
22 /isupport/index.php?include_file=../../../../../etc/resolv.conf 1 1.43
23 /page.php?p=../../../../etc/resolv.conf 1 1.43
24 /page.php?page=../../../../etc/resolv.conf 1 1.43
25 /avr_de/praesentation/favicon.ico 1 1.43
Sum 70 100.00

To top of page

Top 25 of 77 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 17,721 48.88
2 Mozilla/4.0 12,914 35.62
3 Mozilla/4.5 1,437 3.96
4 Opera/9.63 854 2.36
5 Opera/9.62 558 1.54
6 ichiro/3.0 347 0.96
7 FDM 2.x 283 0.78
echobot/echobot-
8 273 0.75
v0.5
9 Yanga 211 0.58
10 - 148 0.41
11 Opera/9.52 115 0.32
12 yacybot 108 0.30
Googlebot-
13 103 0.28
Image/1.0
14 Yandex/1.01.001 91 0.25
15 Opera/9.26 90 0.25
16 Opera/9.25 86 0.24
17 Opera/9.60 84 0.23
18 msnbot/1.1 78 0.22
19 Safari5525.27.1 67 0.18
20 msnbot-media/1.1 53 0.15
21 Opera/9.50 50 0.14
22 Opera/9.24 44 0.12
23 Opera/9.10 44 0.12
24 Mozilla/3.01 43 0.12
25 Java/1.6.0_04 38 0.10
Sum 36,255 100.00

To top of page

Top 25 of 176 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 9,593 26.46
2 MSIE 7.0 7,647 21.09
3 MSIE 6.0 4,191 11.56
4 HTTrack 3.0x 1,434 3.96
5 Firefox/3.0.5 1,045 2.88
6 Gecko 880 2.43
7 Opera/9.63 835 2.30
8 Firefox/2.0.0.20 655 1.81
9 Firefox/3.0.4 642 1.77
10 unknown 604 1.67
11 Firefox/3.0.3 603 1.66
12 Opera/9.62 558 1.54
13 Slurp 533 1.47
14 Firefox/3.0.1 390 1.08
15 crawler.html 347 0.96
16 FDM 298 0.82
17 FDM 2.x 283 0.78
18 crawler 273 0.75
19 MSIE 5.0 230 0.63
20 Firefox/1.5.0.2 227 0.63
21 Firefox/3.0 226 0.62
Gecko/2008112309
22 197 0.54
Iceweasel/3.0.4
23 MSIE 8.0 193 0.53
24 Firefox/2.0.0.18 191 0.53
25 Firefox/2.0.0.14 158 0.44
Sum 36,255 100.00

To top of page

Top 25 of 33 operating systems , sorted by number of files

N operating systems times %


1 Windows 13,414 37.00
2 Windows NT 5.1 11,953 32.97
3 unknown 2,867 7.91
4 Linux i686 2,252 6.21
5 Windows NT 6.0 1,886 5.20
6 Windows 98 1,568 4.32
7 Linux x86_64 404 1.11
8 Windows NT 5.0 345 0.95
9 Windows NT 4.0 222 0.61
10 Linux 211 0.58
11 Mac OS X 10.5 173 0.48
12 Mac OS X 10_5_6 165 0.46
Linux 2.6.27-9-
13 108 0.30
generic
14 Windows XP 5.1 105 0.29
15 Windows NT 5.2 105 0.29
16 Win16 91 0.25
17 Mac OS X 88 0.24
18 Mac OS X 10_4_11 78 0.22
19 Mac OS X 10.4 73 0.20
20 Mac OS X 10_5_5 66 0.18
21 X11 22 0.06
22 Windows 6.0 19 0.05
23 Linux i686 11 0.03
24 Windows server 6 0.02
25 Linux 2.6.26 6 0.02
Sum 36,255 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 1,201 3.31
2 01 1,355 3.74
3 02 1,063 2.93
4 03 776 2.14
5 04 765 2.11
6 05 395 1.09
7 06 1,229 3.39
8 07 958 2.64
9 08 1,368 3.77
10 09 1,069 2.95
11 10 1,317 3.63
12 11 1,737 4.79
13 12 1,832 5.05
14 13 3,242 8.94
15 14 1,607 4.43
16 15 1,863 5.14
17 16 2,216 6.11
18 17 1,796 4.95
19 18 1,819 5.02
20 19 2,331 6.43
21 20 1,680 4.63
22 21 1,953 5.39
23 22 1,328 3.66
24 23 1,355 3.74
Sum 36,255 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w53.html (2 of 2)1/20/2009 8:07:41 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w52

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 52

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 4595 IPs and host names , sorted by number of files

N IPs and host names times %


1 89.61.218.40=Zda28.z.pppool.de 1,161 1.46
2 91.205.124.9=(not found) 644 0.81
3 88.117.110.122=88-117-110-122.adsl.highway.telekom.at 298 0.37
4 67.195.37.116=llf320025.crawl.yahoo.net 290 0.36
5 89.13.93.200=drms-590d5dc8.pool.einsundeins.de 268 0.34
6 141.31.185.49=ip-141-31-185-49.nat.selfnet.de 252 0.32
7 93.158.148.31=spider11.yandex.ru 244 0.31
8 87.234.140.130=port-87-234-140-130.dynamic.qsc.de 231 0.29
9 72.30.161.225=llf531025.crawl.yahoo.net 227 0.29
10 85.178.158.29=e178158029.adsl.alicedsl.de 222 0.28
11 82.212.18.68=HSI-KBW-082-212-018-068.hsi.kabelbw.de 218 0.27
12 66.249.71.205=crawl-66-249-71-205.googlebot.com 208 0.26
13 24.125.218.251=c-24-125-218-251.hsd1.va.comcast.net 200 0.25
14 66.249.71.206=crawl-66-249-71-206.googlebot.com 196 0.25
15 217.233.113.63=pD9E9713F.dip.t-dialin.net 193 0.24
16 66.249.71.207=crawl-66-249-71-207.googlebot.com 192 0.24
78.42.50.197=HSI-KBW-078-042-050-197.hsi3.kabel-badenwuerttemberg.
17 191 0.24
de
18 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 175 0.22
19 82.121.28.8=ASte-Genev-Bois-152-1-14-8.w82-121.abo.wanadoo.fr 175 0.22
20 200.69.182.248=248.182.uio.satnet.net 174 0.22
21 76.31.26.12=c-76-31-26-12.hsd1.tx.comcast.net 173 0.22
22 91.55.244.229=p5B37F4E5.dip.t-dialin.net 171 0.21
23 93.147.121.93=net-93-147-121-93.t2.dsl.vodafone.it 167 0.21
24 202.56.7.7=(not found) 161 0.20
25 80.143.230.33=p508FE621.dip.t-dialin.net 153 0.19
Sum 79,584 100.00

To top of page

Top 25 of 4595 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.205.124.9=(not found) 19,664 2.35
2 77.22.115.197=(not found) 17,152 2.05
3 194.147.209.5=proxy.rega.ch 10,529 1.26
4 88.117.110.122=88-117-110-122.adsl.highway.telekom.at 7,497 0.90
5 77.135.44.87=BAH2c57.bah.pppool.de 6,498 0.78
6 87.171.98.52=p57AB6234.dip.t-dialin.net 6,346 0.76
7 79.210.124.223=p4FD27CDF.dip.t-dialin.net 6,200 0.74
8 72.30.161.225=llf531025.crawl.yahoo.net 5,311 0.63
9 77.181.255.81=dsbg-4db5ff51.pool.einsundeins.de 5,228 0.62
10 67.195.37.116=llf320025.crawl.yahoo.net 4,862 0.58
79.25.107.72=host72-107-dynamic.25-79-r.retail.telecomitalia.
11 4,664 0.56
it
12 217.84.250.172=pD954FAAC.dip0.t-ipconnect.de 4,519 0.54
13 93.158.148.31=spider11.yandex.ru 4,485 0.54
14 89.182.218.186=a89-182-218-186.net-htp.de 4,063 0.49
15 84.141.49.74=p548D314A.dip0.t-ipconnect.de 4,002 0.48
16 91.38.160.132=p5B26A084.dip0.t-ipconnect.de 3,898 0.47
17 77.183.70.62=brmn-4db7463e.pool.einsundeins.de 3,843 0.46
18 62.214.215.73=i3ED6D749.versanet.de 3,823 0.46
19 68.142.215.155=crm92.image.search.mud.yahoo.net 3,808 0.45
20 88.130.200.229=(not found) 3,784 0.45
21 217.231.117.242=pD9E775F2.dip.t-dialin.net 3,681 0.44
22 74.6.18.239=llf520135.crawl.yahoo.net 3,645 0.44
23 89.61.218.40=Zda28.z.pppool.de 3,579 0.43
24 80.143.206.77=p508FCE4D.dip.t-dialin.net 3,534 0.42
25 85.178.161.49=e178161049.adsl.alicedsl.de 3,408 0.41
Sum 837,592 100.00

To top of page

Top 25 of 738 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.207=crawl-66-249-71-207.googlebot.com 88 2.82
2 66.249.71.205=crawl-66-249-71-205.googlebot.com 81 2.60
3 66.249.71.206=crawl-66-249-71-206.googlebot.com 78 2.50
4 67.195.37.116=llf320025.crawl.yahoo.net 63 2.02
5 72.30.161.225=llf531025.crawl.yahoo.net 55 1.76
6 193.47.80.44=crawl8.exabot.com 39 1.25
7 67.195.37.111=llf320022.crawl.yahoo.net 38 1.22
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 36 1.15
9 81.52.143.16=natcrawlbloc03.net.m1.fti.net 36 1.15
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 35 1.12
11 81.52.143.26=natcrawlbloc05.net.m1.fti.net 31 0.99
12 74.6.18.239=llf520135.crawl.yahoo.net 26 0.83
13 58.239.73.120=(not found) 25 0.80
14 88.131.106.16=(not found) 23 0.74
15 67.195.37.189=llf320053.crawl.yahoo.net 23 0.74
16 65.55.212.136=(not found) 22 0.70
17 67.195.37.185=llf320047.crawl.yahoo.net 21 0.67
65.55.209.167=msnbot-65-55-209-167.search.msn.
18 21 0.67
com
19 193.252.149.16=natcrawlbloc04.net.s1.fti.net 20 0.64
20 193.39.71.5=lochowska.dag.pl 18 0.58
65.55.209.166=msnbot-65-55-209-166.search.msn.
21 18 0.58
com
65.55.209.159=msnbot-65-55-209-159.search.msn.
22 17 0.54
com
23 72.30.65.42=llf531365.crawl.yahoo.net 16 0.51
24 212.143.177.197=(not found) 16 0.51
65.55.209.152=msnbot-65-55-209-152.search.msn.
25 16 0.51
com
Sum 3,121 100.00

To top of page

Top 25 of 88 countries of origin , sorted by number of files

N countries of origin times %


1 net 25,940 32.59
2 Germany 18,563 23.33
3 (unresolved) 12,133 15.25
4 com 5,293 6.65
5 Poland 2,491 3.13
6 Austria 1,770 2.22
7 Netherlands 1,122 1.41
8 Switzerland 1,079 1.36
9 Italy 1,072 1.35
10 Hungary 756 0.95
11 India 684 0.86
12 Belgium 530 0.67
13 Russian Federation 493 0.62
14 Canada 458 0.58
15 France 451 0.57
16 Czech Republic 406 0.51
17 Sweden 372 0.47
18 Finland 333 0.42
19 Romania 332 0.42
20 Indonesia 325 0.41
21 Greece 323 0.41
22 Australia 312 0.39
23 Slovak Republic 259 0.33
24 Mexico 259 0.33
25 Lithuania 251 0.32
Sum 79,584 100.00

To top of page

Top 25 of 115 pathes , sorted by number of files

N pathes times %
1 /common/ 29,162 36.64
2 /avr_gra/ 12,711 15.97
3 / 9,135 11.48
4 /avr_en/beginner/ 3,120 3.92
5 /avr_de/beginner/ 2,566 3.22
6 /avr_de/ 2,479 3.11
7 /avr_en/ 2,347 2.95
8 /avr_de/fcount/ 1,454 1.83
9 /avr_en/calc/ 1,286 1.62
10 /avr_de/rechnen/ 1,224 1.54
11 /avr_de/praesentation/ 1,126 1.41
12 /avr_de/stepper/ 1,046 1.31
13 /avr_en/source/ 851 1.07
14 /avr_en/keypad/ 818 1.03
15 /avr_de/quellen/ 755 0.95
16 /avr_en/signalgen/pics/ 647 0.81
17 /avr_de/keypad/ 579 0.73
18 /gavrasm/ 570 0.72
19 /avr_de/zeitschleifen/ 529 0.66
/avr_de/rechteckgen/
20 508 0.64
bilder/
21 /avr_de/interrupts/ 477 0.60
22 /avr_en/stepper/ 465 0.58
23 /privat/heppenh/ 359 0.45
24 /akkuload/ 340 0.43
25 /privat/magloop/ 303 0.38
Sum 79,584 100.00

To top of page

Top 25 of 115 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 175,360 20.94
2 /avr_gra/ 95,083 11.35
3 /avr_de/intro/pdf/ 78,625 9.39
4 / 52,338 6.25
5 /avr_de/fcount/ 51,544 6.15
6 /avr_de/ 36,969 4.41
7 /avr_en/ 32,728 3.91
8 /avr_de/stepper/ 27,606 3.30
9 /avr_en/beginner/ 25,982 3.10
10 /avr_de/beginner/ 23,056 2.75
11 /gavrasm/v22/ 22,314 2.66
12 /avr_en/signalgen/pics/ 17,037 2.03
13 /privat/magloop/ 14,743 1.76
14 /common/ 13,667 1.63
/avr_de/rechteckgen/
15 12,899 1.54
bilder/
16 /avr_en/signalgen/ 11,910 1.42
17 /avr_en/calc/ 11,329 1.35
18 /avr_en/stepper/ 11,322 1.35
19 /avr_de/rechnen/ 9,613 1.15
20 /avr_de/intro/ppt/ 9,033 1.08
21 /akkuload/ 8,298 0.99
22 /avr_de/rechteckgen/ 6,927 0.83
23 /avr_en/keypad/ 6,039 0.72
24 /privat/heppenh/ 5,552 0.66
25 /avr_de/interrupts/ 4,923 0.59
Sum 837,592 100.00

To top of page

Top 25 of 1566 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 3,928 4.94
2 /avr_gra/RingLogo.jpg 2,264 2.84
3 /common/akkuload.gif 1,890 2.37
/common/download.
4 1,888 2.37
gif
5 /common/app.gif 1,886 2.37
/common/knowhow.
6 1,884 2.37
gif
7 /common/adc.gif 1,876 2.36
8 /common/gavrasm.gif 1,875 2.36
9 /common/example.gif 1,871 2.35
/common/gavrasmw.
10 1,871 2.35
gif
11 /common/keyb.gif 1,869 2.35
12 /common/calc.gif 1,868 2.35
13 /avr_gra/stk_lcd.jpg 1,867 2.35
14 /common/clock.gif 1,867 2.35
15 /common/r2r.gif 1,867 2.35
16 /common/hardware.gif 1,866 2.34
17 /common/beginner.gif 1,864 2.34
18 /index.html 1,313 1.65
19 /avr_en/index.html 1,123 1.41
20 /avr_de/index.html 1,086 1.36
21 /avr_2313.gif 1,005 1.26
22 /avr-asm-tutorial.gif 1,003 1.26
23 /dg4fac.gif 1,003 1.26
24 /common/delay.gif 974 1.22
25 /common/ints.gif 973 1.22
Sum 79,584 100.00

To top of page

Top 25 of 1566 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 59,207 7.07
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 33,358 3.98
3 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 31,075 3.71
/avr_de/praesentation/Teil_5b_Beispiel01_02.
4 27,074 3.23
pdf
5 /avr_de/index.html 24,267 2.90
6 /avr_en/index.html 23,354 2.79
7 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 22,578 2.70
8 /avr_2313.gif 17,775 2.12
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 16,828 2.01
10 /dg4fac.gif 10,645 1.27
11 /avr_de/fcount/dscf0004.jpg 10,476 1.25
12 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 10,168 1.21
13 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 9,432 1.13
14 /avr_de/fcount/dscf0005.jpg 9,107 1.09
15 /avr_gra/pwm_simul.jpg 8,824 1.05
16 /avr_de/fcount/dscf0001.jpg 8,412 1.00
17 /avr_en/signalgen/pics/rectgen_wiring.jpg 7,964 0.95
18 /favicon.ico 7,748 0.93
19 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 7,291 0.87
20 /avr_en/signalgen/rectgen_m8.xls 7,194 0.86
21 /index.html 6,888 0.82
22 /avr_de/stepper/stepper_v1.gif 6,837 0.82
23 /avr_gra/r2r_hardware.jpg 6,821 0.81
24 /avr_de/fcount/fcount.jpg 6,527 0.78
25 /gavrasm/v22/gavrasm_win_de_22.zip 6,452 0.77
Sum 837,592 100.00

To top of page

Top 25 of 485 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,313 7.75
2 /avr_en/index.html 1,123 6.63
3 /avr_de/index.html 1,086 6.41
4 /avr_en/beginner/index.html 543 3.21
5 /avr_en/beginner/RIGHT.html 535 3.16
6 /avr_en/beginner/LEFT.html 515 3.04
7 /avr_de/beginner/rechts.html 383 2.26
8 /avr_de/beginner/index.html 377 2.23
9 /avr_de/beginner/links.html 361 2.13
/avr_en/beginner/HARDWARE.
10 204 1.20
html
11 /avr_en/beginner/REGISTER.html 201 1.19
12 /avr_de/beginner/hardware.html 177 1.04
13 /avr_en/keypad/keyboard.html 174 1.03
14 /avr_de/praesentation/index.html 171 1.01
15 /avr_en/beginner/JUMP.html 158 0.93
16 /avr_de/beginner/register.html 150 0.89
17 /avr_de/stepper/stepper.html 144 0.85
18 /avr_en/AVR_TUT.html 136 0.80
19 /avr_de/fcount/fcount_m8.html 135 0.80
20 /avr_de/apps.html 134 0.79
21 /avr_en/beginner/SRAM.html 131 0.77
22 /avr_de/beginner/werkzeuge.html 128 0.76
23 /avr_de/avr_tut.html 128 0.76
24 /avr_de/beginner/sprung.html 126 0.74
25 /avr_de/keypad/keyboard.html 126 0.74
Sum 16,938 100.00

To top of page

Top 25 of 485 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 24,267 13.58
2 /avr_en/index.html 23,354 13.07
3 /index.html 6,888 3.86
4 /avr_en/beginner/RIGHT.html 3,832 2.14
5 /avr_en/beginner/JUMP.html 3,692 2.07
6 /avr_en/keypad/keyboard.html 3,402 1.90
7 /avr_de/beginner/sprung.html 3,348 1.87
8 /avr_de/dcf77uhr.html 3,159 1.77
9 /gb_new.html 2,754 1.54
10 /avr_de/beginner/rechts.html 2,624 1.47
11 /avr_de/keypad/keyboard.html 2,442 1.37
12 /avr_en/beginner/LEFT.html 2,360 1.32
13 /avr_en/beginner/CALC.html 2,314 1.30
14 /avr_de/beginner/rechnen.html 2,295 1.28
15 /avr_en/beginner/REGISTER.html 2,285 1.28
16 /avr_de/stepper/stepper.html 2,128 1.19
17 /avr_de/beginner/commands.html 2,090 1.17
18 /avr_en/signalgen/rectgen_m8.html 2,016 1.13
19 /sitemap_de.html 1,900 1.06
/avr_en/beginner/COMMANDS.
20 1,809 1.01
html
21 /avr_de/interrupts/int_quellen.html 1,776 0.99
22 /avr_en/beginner/PDETAIL.html 1,764 0.99
/avr_de/rechteckgen/rectgen_m8.
23 1,738 0.97
html
24 /avr_de/beginner/pdetail.html 1,711 0.96
25 /avr_de/avr_dac.html 1,692 0.95
Sum 178,663 100.00

To top of page

Top 25 of 404 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,260 19.58
2 /avr_gra/stk_lcd.jpg 1,867 16.17
3 /avr_gra/avr_isp.jpg 344 2.98
4 /avr_gra/exp_2313.jpg 341 2.95
5 /avr_gra/exp2313g.jpg 341 2.95
6 /avr_gra/8515.jpg 338 2.93
7 /avr_gra/AT90S8515.jpg 233 2.02
8 /avr_gra/r2r_wave.jpg 224 1.94
9 /avr_gra/r2r_sawtooth.jpg 205 1.78
10 /avr_gra/r2r_hardware.jpg 189 1.64
11 /avr_gra/r2r_triangle.jpg 188 1.63
12 /avr_gra/r2r_sawtoothupperbound.jpg 188 1.63
13 /avr_gra/r2r_sawtooth741.jpg 186 1.61
14 /avr_gra/r2r_upperbound.jpg 184 1.59
15 /avr_gra/apps.jpg 176 1.52
16 /akkuload/dscf0030s.jpg 162 1.40
17 /avr_gra/pwm_simul.jpg 162 1.40
18 /avr_gra/adc8conn.jpg 161 1.39
19 /avr_de/praesentation/zuendtester.jpg 158 1.37
20 /avr_de/stepper/stepper_sm.jpg 147 1.27
21 /avr_de/stepper/kp4m4-001.jpg 139 1.20
22 /avr_de/stepper/supply.jpg 137 1.19
23 /avr_de/stepper/driver.jpg 134 1.16
/avr_en/signalgen/pics/rectgen_280.
24 131 1.13
jpg
25 /avr_de/fcount/fcount_sm.jpg 130 1.13
Sum 11,544 100.00

To top of page

Top 25 of 379 GIF-files , sorted by number of files

N GIF-files times %
1 /common/akkuload.gif 1,887 4.42
/common/download.
2 1,885 4.42
gif
3 /common/app.gif 1,883 4.41
/common/knowhow.
4 1,881 4.41
gif
5 /common/adc.gif 1,873 4.39
6 /common/gavrasm.gif 1,872 4.39
7 /common/example.gif 1,868 4.38
/common/gavrasmw.
8 1,868 4.38
gif
9 /common/keyb.gif 1,866 4.37
10 /common/calc.gif 1,865 4.37
11 /common/clock.gif 1,864 4.37
12 /common/r2r.gif 1,864 4.37
13 /common/hardware.gif 1,863 4.37
14 /common/beginner.gif 1,861 4.36
15 /avr_2313.gif 1,005 2.35
16 /avr-asm-tutorial.gif 1,003 2.35
17 /dg4fac.gif 1,003 2.35
18 /common/delay.gif 971 2.28
19 /common/ints.gif 970 2.27
20 /common/tn13.gif 969 2.27
21 /avr_gra/2313.gif 837 1.96
22 /avr_gra/exp2313.gif 352 0.82
23 /avr_gra/avr_isp.gif 346 0.81
24 /avr_gra/isp10pin.gif 342 0.80
25 /avr_gra/isp6pin.gif 341 0.80
Sum 42,678 100.00

To top of page

Top 25 of 169 entry pages , sorted by number of files

N entry pages times %


1 /index.html 664 19.01
2 /avr_en/index.html 432 12.37
3 /avr_de/index.html 342 9.79
4 /avr_en/beginner/index.html 163 4.67
5 /avr_de/beginner/index.html 96 2.75
6 /avr_de/fcount/fcount_m8.html 74 2.12
7 /avr_de/stepper/stepper.html 74 2.12
8 /avr_en/keypad/keyboard.html 66 1.89
9 /avr_en/AVR_DAC.html 60 1.72
10 /avr_en/beginner/HARDWARE.html 59 1.69
11 /avr_en/signalgen/rectgen_m8.html 57 1.63
12 /avr_de/keypad/keyboard.html 53 1.52
13 /avr_de/avr_dac.html 49 1.40
/avr_de/rechteckgen/rectgen_m8.
14 45 1.29
html
15 /avr_de/beginner/hardware.html 36 1.03
16 /avr_en/beginner/SRAM.html 35 1.00
17 /avr_de/lcd4_500.html 35 1.00
18 /avr_de/rechnen/konversion.html 35 1.00
19 /avr_de/intro/index.html 34 0.97
20 /avr_en/beginner/REGISTER.html 33 0.94
21 /avr_de/avr_adc500.html 32 0.92
22 /avr_en/AVR_ADC500.html 30 0.86
23 /avr_en/stepper/stepper.html 28 0.80
24 /akkuload/de/index.html 27 0.77
25 /avr_de/beginner/werkzeuge.html 26 0.74
Sum 3,493 100.00

To top of page

Top 25 of 201 cheat pages , sorted by number of files

N cheat pages times %


1 694 15.10
2 /index.html 387 8.42
3 /avr_en/index.html 360 7.83
4 /avr_de/index.html 285 6.20
5 /avr_en/beginner/RIGHT.html 104 2.26
6 /avr_en/keypad/keyboard.html 85 1.85
7 /avr_de/stepper/stepper.html 81 1.76
8 /avr_de/fcount/fcount_m8.html 75 1.63
9 /avr_en/beginner/HARDWARE.html 73 1.59
10 /avr_en/AVR_DAC.html 68 1.48
11 /avr_en/beginner/REGISTER.html 66 1.44
12 /avr_de/keypad/keyboard.html 64 1.39
13 /avr_de/avr_dac.html 60 1.31
14 /avr_de/beginner/rechts.html 54 1.18
15 /akkuload/de/index.html 50 1.09
16 /avr_de/praesentation/index.html 49 1.07
17 /avr_de/beginner/hardware.html 49 1.07
18 /avr_en/beginner/JUMP.html 49 1.07
19 /avr_en/signalgen/rectgen_m8.html 47 1.02
20 /avr_en/beginner/SRAM.html 44 0.96
21 /avr_de/beginner/werkzeuge.html 43 0.94
22 /avr_en/AVR_ADC500.html 41 0.89
/avr_de/rechteckgen/rectgen_m8.
23 41 0.89
html
24 /avr_de/intro/index.html 36 0.78
25 /avr_en/beginner/TOOLS.html 36 0.78
Sum 4,595 100.00

To top of page

Top 25 of 157 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,578 17.55
2 /avr_en/beginner/index.html 924 10.28
3 /avr_de/beginner/index.html 646 7.19
4 / 549 6.11
5 /avr_en/index.html 534 5.94
6 /avr_en/ 464 5.16
7 /avr_en/beginner/RIGHT.html 408 4.54
8 /avr_en/beginner/LEFT.html 388 4.32
9 /avr_de/beginner/rechts.html 352 3.92
10 /avr_de/beginner/links.html 291 3.24
11 /sitemap_de.html 235 2.61
12 /avr_de/apps.html 182 2.02
13 /index.html 159 1.77
14 /sitemap_en.html 137 1.52
15 /avr_de/interrupts/index.html 137 1.52
16 /avr_en/AVR_TUT.html 117 1.30
17 /avr_de/rechnen/index.html 116 1.29
18 /avr_de/zeitschleifen/index.html 110 1.22
19 /avr_en/calc/index.html 109 1.21
20 /avr_de/avr_tut.html 107 1.19
21 /weblox_de/index.html 75 0.83
22 /avr_de/ 74 0.82
23 /weblox_en/index.html 74 0.82
24 /avr_en/APPS.html 58 0.65
/avr_en/signalgen/rectgen_m8.
25 49 0.55
html
Sum 8,989 100.00

To top of page

Top 25 of 378 external referrers , sorted by number of files

N external referrers times %


1 - 4,529 83.56
2 http://www.webring.com/hub?ring=avr 46 0.85
3 http://www.mikrocontroller.net/articles/AVR 29 0.54
4 http://www.rowalt.de/mc/avr/linksd.htm 19 0.35
5 http://www.dg4fac.de/linksunten.html 18 0.33
6 http://www.mikrocontroller.net/topic/120235 18 0.33
7 http://avr-asm.tripod.com/ 14 0.26
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
8 14 0.26
ESC_by1_bz0_bs0.html
9 http://www.dg4fac.de/rechtsunten.html 14 0.26
10 http://de.wikipedia.org/wiki/R2R-Netzwerk 13 0.24
11 http://blackstrom.derschwarz.de/avr/avr/index.shtml 11 0.20
http://www.avrfreaks.net/index.php?
12 name=PNphpBB2&file=viewtopic&t=7067 11 0.20
3
13 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 10 0.18
14 http://frank.bol.ucla.edu/avr.htm 10 0.18
15 http://www.raw.to/rubriken/private_elektronik.html 10 0.18
16 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 10 0.18
17 http://forums.gentoo.org/viewtopic-t-720707.html 10 0.18
18 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 10 0.18
http://electrons.psychogenic.com/modules/arms/art/3/
19 AVRGCCProgrammingG 9 0.17
uide.php
20 http://www.qrpedia.com/blog/n9puz/200812/n9puz-qrv-qrpedia 8 0.15
21 http://www.educypedia.be/electronics/avr.htm 8 0.15
22 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 8 0.15
23 http://it.wikipedia.org/wiki/Atmel_AVR 8 0.15
24 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 7 0.13
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
25 7 0.13
kurs.htm
Sum 5,420 100.00

To top of page

Top 25 of 110 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,020 42.80
2 http://www.google.com 476 19.97
3 http://www.google.co.in 61 2.56
4 http://www.google.at 60 2.52
5 http://www.google.nl 45 1.89
6 http://www.google.ch 40 1.68
7 http://www.google.co.uk 39 1.64
8 http://www.google.pl 38 1.59
9 http://www.google.ca 32 1.34
http://www.google.com.
10 26 1.09
au
11 http://www.google.se 26 1.09
12 http://www.google.hu 22 0.92
http://www.google.com.
13 21 0.88
vn
14 http://www.google.gr 20 0.84
15 http://www.google.fi 19 0.80
16 http://www.google.co.id 18 0.76
17 http://search.live.com 18 0.76
http://de.search.yahoo.
18 17 0.71
com
19 http://www.google.it 16 0.67
20 http://www.google.ro 16 0.67
21 http://www.google.cz 15 0.63
22 http://www.google.be 15 0.63
23 http://www.google.fr 14 0.59
24 http://www.google.lt 14 0.59
http://www.google.com.
25 11 0.46
hk
Sum 2,383 100.00

To top of page

Top 25 of 1614 search strings , sorted by number of files

N search strings times %


1 avr tutorial 83 3.48
2 avr 46 1.93
3 avr assembler 38 1.59
4 assembler 26 1.09
5 avr programming 20 0.84
avr assembler
6 15 0.63
tutorial
7 assembler tutorial 14 0.59
8 avr assembly 13 0.55
9 avr programing 12 0.50
10 attiny13 12 0.50
11 avr asm 12 0.50
12 avr asm tutorial 12 0.50
13 ATtiny13 11 0.46
14 programming avr 11 0.46
15 assembler lernen 10 0.42
16 avr keypad 10 0.42
17 AVR 10 0.42
18 atmega8 8 0.34
19 STK500 8 0.34
20 katomic 8 0.34
21 frequenzzähler avr 8 0.34
22 avr dac 7 0.29
23 AVR Tutorial 7 0.29
24 wavrasm 7 0.29
25 avr assembly tutorial 6 0.25
Sum 2,383 100.00

To top of page

Top 8 of 8 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 69,087 86.81
2 304 Not changed 9,428 11.85
3 206 Partial information 610 0.77

http://www.avr-asm-tutorial.net/weblox_en/2008w52.html (1 of 2)1/20/2009 8:08:00 PM


Weblog statistic for http://www.avr-asm-tutorial.net

4 301 Permanently moved 198 0.25


5 404 File not found 175 0.22
6 403 Forbidden 44 0.06
7 300 Multiple choices 29 0.04
8 405 Method not allowed 13 0.02
Sum 79,584 100.00

To top of page

Top 25 of 65 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 55 31.43
2 /beginner_de.pdf 27 15.43
/_vti_bin/owssvr.dll?
3 9 5.14
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
4 /_vti_inf.html 8 4.57
/MSOffice/cltreq.asp?
5 8 4.57
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/privat/magloop/errors.php?error=http://flowskatepark.org/WebCalendar-
6 3 1.71
1.0.4/includes/mod_poll.txt??
/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/includes/
7 3 1.71
mod_poll.txt??
/privat/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/in
8 3 1.71
cludes/mod_poll.txt??
9 /avr_de/intro/ppt/beispiel10_snd.wav 2 1.14
//auctions/includes/messages.inc.php?include_path=http://www.tanuki.ru
10 2 1.14
/readme.txt?
11 /MarkAny/Websafer/MaSiteInfo.ini 1 0.57
/_vti_bin/owssvr.dll?
12 1 0.57
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 1 0.57
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
14 /twiki/bin/configure?action=image;image=|id|;type=text/plain 1 0.57
15 /typo3conf/localconf.php 1 0.57
16 /sitecore/login/index.html 1 0.57
/_vti_bin/owssvr.dll?
17 1 0.57
UL=1&ACT=4&BUILD=6211&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
18 1 0.57
UL=1&ACT=4&BUILD=6211&STRMVER=4&CAPREQ=0
19 /avr_en/DIVISION.html 1 0.57
20 /avr_en/FPCONV.html 1 0.57
21 /avr_en/HARDMULT.html 1 0.57
22 /de 1 0.57
23 /akkuload/akkucalc.asm 1 0.57
24 /gavrasmi.html 1 0.57
25 /index_de.html 1 0.57
Sum 175 100.00

To top of page

Top 25 of 115 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 42,889 53.89
2 Mozilla/4.0 28,177 35.41
3 Opera/9.62 1,705 2.14
4 Opera/9.63 1,674 2.10
5 - 1,281 1.61
6 Yanga 650 0.82
7 msnbot/1.1 358 0.45
8 Opera/9.60 280 0.35
9 Opera/9.50 247 0.31
10 Yandex/1.01.001 244 0.31
Googlebot-
11 234 0.29
Image/1.0
12 Opera/9.52 185 0.23
13 Opera/9.61 144 0.18
14 Opera/9.51 125 0.16
15 msnbot-media/1.0 121 0.15
16 panscient.com 121 0.15
17 msnbot-media/1.1 115 0.14
18 Opera/9.22 101 0.13
19 Opera/9.23 74 0.09
20 Safari5525.27.1 66 0.08
21 Opera/9.27 64 0.08
22 Opera/10.00 61 0.08
23 Opera/9.10 57 0.07
24 Mozilla/3.01 49 0.06
25 Opera/9.24 43 0.05
Sum 79,584 100.00

To top of page

Top 25 of 251 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.5 22,014 27.66
2 MSIE 7.0 16,920 21.26
3 MSIE 6.0 8,879 11.16
4 Firefox/3.0.4 3,906 4.91
5 Firefox/3.0.5 2,658 3.34
6 unknown 2,457 3.09
7 Gecko 2,150 2.70
8 Firefox/2.0.0.20 1,816 2.28
9 Opera/9.62 1,705 2.14
10 Opera/9.63 1,674 2.10
11 Slurp 1,115 1.40
12 Firefox/3.0.1 985 1.24
13 FDM 846 1.06
14 Firefox/3.0.3 704 0.88
15 Firefox/3.0 513 0.64
16 Firefox/2.0.0.18 513 0.64
17 MSIE 8.0 430 0.54
18 Firefox/2.0.0.12 390 0.49
19 msnbot/1.1 358 0.45
20 Googlebot/2.1 352 0.44
Gecko/2008112309
21 316 0.40
Iceweasel/3.0.4
22 Firefox/2.0 313 0.39
23 Slurp/3.0 310 0.39
24 Opera/9.60 280 0.35
25 Yandex/1.01.001 244 0.31
Sum 79,584 100.00

To top of page

Top 25 of 46 operating systems , sorted by number of files

N operating systems times %


1 Windows 33,069 41.55
2 Windows NT 5.1 25,259 31.74
3 unknown 5,873 7.38
4 Windows NT 6.0 4,762 5.98
5 Linux i686 4,710 5.92
6 Windows NT 5.0 1,267 1.59
7 Linux x86_64 969 1.22
8 Mac OS X 10.5 554 0.70
9 Windows 98 504 0.63
10 Mac OS X 10_5_6 388 0.49
11 Mac OS X 350 0.44
12 Windows NT 5.2 338 0.42
13 Linux i686 317 0.40
14 Win16 246 0.31
15 Windows XP 5.1 181 0.23
16 Mac OS X 10_5_5 153 0.19
17 Mac OS X 10.4 115 0.14
Mac OS X
18 100 0.13
10_4_11
19 Mac OS X 10_5_4 77 0.10
20 Linux 68 0.09
21 Windows 6.0 48 0.06
22 Windows 32-bit 46 0.06
23 X11 42 0.05
24 Mac OS X 10_5_3 27 0.03
25 Mac OS X Mach-O 24 0.03
Sum 79,584 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 3,006 3.78
2 01 2,308 2.90
3 02 2,070 2.60
4 03 2,227 2.80
5 04 1,091 1.37
6 05 1,017 1.28
7 06 1,019 1.28
8 07 1,661 2.09
9 08 2,410 3.03
10 09 2,226 2.80
11 10 3,192 4.01
12 11 3,602 4.53
13 12 5,694 7.15
14 13 4,128 5.19
15 14 4,673 5.87
16 15 4,481 5.63
17 16 4,149 5.21
18 17 4,934 6.20
19 18 4,963 6.24
20 19 3,864 4.86
21 20 4,583 5.76
22 21 4,017 5.05
23 22 4,088 5.14
24 23 4,181 5.25
Sum 79,584 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w52.html (2 of 2)1/20/2009 8:08:00 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w51

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 51

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5510 IPs and host names , sorted by number of files

N IPs and host names times %


1 91.205.124.9=(not found) 1,061 1.16
2 91.191.10.139=(not found) 754 0.83
3 62.218.64.137=simmu1-64-137.utaonline.at 751 0.82
4 84.168.114.83=p54A87253.dip.t-dialin.net 610 0.67
5 141.31.185.49=ip-141-31-185-49.nat.selfnet.de 450 0.49
6 85.196.177.200=cm-200-177-vr.m-real.net 447 0.49
7 89.53.117.221=Q75dd.q.strato-dslnet.de 344 0.38
8 208.115.111.244=crawl3.dotnetdotcom.org 342 0.37
9 77.237.190.172=(not found) 312 0.34
10 67.195.37.116=llf320025.crawl.yahoo.net 306 0.34
11 72.30.81.182=llf531210.crawl.yahoo.net 295 0.32
12 89.207.216.213=(not found) 291 0.32
13 66.74.200.194=cpe-66-74-200-194.san.res.rr.com 275 0.30
14 94.222.58.61=(not found) 269 0.29
15 164.3.25.10=axion.voest.at 256 0.28
16 212.200.100.100=wifi.info-net.co.yu 255 0.28
17 141.35.184.153=4165-01ad16.stw-wh.uni-jena.de 250 0.27
18 89.52.116.109=P746d.p.pppool.de 232 0.25
19 208.111.154.16=crawl2.nat.svl.searchme.com 230 0.25
20 24.22.91.154=c-24-22-91-154.hsd1.or.comcast.net 219 0.24
66.249.71.205=crawl-66-249-71-205.googlebot.
21 209 0.23
com
22 62.220.3.130=mail.bwb.de 201 0.22
66.249.71.207=crawl-66-249-71-207.googlebot.
23 200 0.22
com
24 67.195.37.95=llf320039.crawl.yahoo.net 200 0.22
25 86.90.112.152=ip565a7098.direct-adsl.nl 198 0.22
Sum 91,331 100.00

To top of page

Top 25 of 5510 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.191.10.139=(not found) 29,015 2.89
2 62.218.64.137=simmu1-64-137.utaonline.at 29,006 2.88
3 84.168.114.83=p54A87253.dip.t-dialin.net 26,755 2.66
4 91.205.124.9=(not found) 24,886 2.47
5 77.178.177.72=dtmd-4db2b148.pool.einsundeins.de 17,225 1.71
6 77.22.115.197=(not found) 11,403 1.13
7 80.140.123.124=p508C7B7C.dip.t-dialin.net 11,348 1.13
8 77.20.16.74=(not found) 11,000 1.09
9 89.53.117.221=Q75dd.q.strato-dslnet.de 8,682 0.86
10 86.90.112.152=ip565a7098.direct-adsl.nl 7,089 0.70
11 77.237.190.172=(not found) 7,072 0.70
12 72.30.81.182=llf531210.crawl.yahoo.net 6,722 0.67
13 89.207.216.213=(not found) 6,110 0.61
88.74.153.165=dslb-088-074-153-165.pools.arcor-ip.
14 5,403 0.54
net
15 92.202.67.166=port-92-202-67-166.dynamic.qsc.de 4,769 0.47
16 67.195.37.95=llf320039.crawl.yahoo.net 4,454 0.44
82.82.211.216=dslc-082-082-211-216.pools.arcor-ip.
17 4,230 0.42
net
18 87.78.132.236=xdsl-87-78-132-236.netcologne.de 4,219 0.42
19 78.49.50.16=f049050016.adsl.alicedsl.de 4,149 0.41
20 87.160.125.162=p57A07DA2.dip.t-dialin.net 4,082 0.41
21 84.44.215.67=xdsl-84-44-215-67.netcologne.de 3,810 0.38
22 84.164.126.204=p54A47ECC.dip.t-dialin.net 3,615 0.36
23 213.196.198.4=xdsl-213-196-198-4.netcologne.de 3,549 0.35
24 84.147.92.87=p54935C57.dip.t-dialin.net 3,519 0.35
25 62.157.214.73=(not found) 3,469 0.34
Sum 1,005,642 100.00

To top of page

Top 25 of 869 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 66.249.71.207=crawl-66-249-71-207.googlebot.com 83 2.37
2 66.249.71.205=crawl-66-249-71-205.googlebot.com 83 2.37
3 67.195.37.116=llf320025.crawl.yahoo.net 77 2.20
4 208.111.154.16=crawl2.nat.svl.searchme.com 67 1.91
5 66.249.71.206=crawl-66-249-71-206.googlebot.com 62 1.77
6 208.111.154.15=crawl1.nat.svl.searchme.com 59 1.69
7 208.115.111.244=crawl3.dotnetdotcom.org 55 1.57
8 72.30.81.182=llf531210.crawl.yahoo.net 52 1.49
9 193.47.80.44=crawl8.exabot.com 47 1.34
10 67.195.37.95=llf320039.crawl.yahoo.net 34 0.97
11 81.52.143.16=natcrawlbloc03.net.m1.fti.net 34 0.97
12 66.235.124.3=crawler5003.ask.com 33 0.94
13 81.52.143.26=natcrawlbloc05.net.m1.fti.net 31 0.89
14 81.52.143.15=natcrawlbloc01.net.m1.fti.net 30 0.86
15 193.252.149.15=natcrawlbloc02.net.s1.fti.net 27 0.77
16 141.31.185.49=ip-141-31-185-49.nat.selfnet.de 21 0.60
17 220.181.61.229=(not found) 20 0.57
18 65.55.209.158=msnbot-65-55-209-158.search.msn.com 18 0.51
19 65.55.209.153=msnbot-65-55-209-153.search.msn.com 17 0.49
20 78.99.80.88=adsl-dyn88.78-99-80.t-com.sk 16 0.46
21 193.252.149.16=natcrawlbloc04.net.s1.fti.net 15 0.43
22 85.18.227.211=85-18-227-211.ip.fastwebnet.it 14 0.40
23 67.195.37.189=llf320053.crawl.yahoo.net 14 0.40
24 80.202.224.153=153.80-202-224.nextgentel.com 13 0.37
75.101.227.34=ec2-75-101-227-34.compute-1.amazonaws.
25 13 0.37
com
Sum 3,501 100.00

To top of page

Top 25 of 95 countries of origin , sorted by number of files

N countries of origin times %


1 net 25,295 27.70
2 Germany 19,375 21.21
3 (unresolved) 18,219 19.95
4 com 6,441 7.05
5 Austria 2,773 3.04
6 Poland 1,808 1.98
7 Netherlands 1,613 1.77
8 Switzerland 1,519 1.66
9 Italy 1,061 1.16
10 India 1,018 1.11
11 Hungary 1,004 1.10
12 Indonesia 763 0.84
13 Lithuania 646 0.71
14 Czech Republic 541 0.59
15 Greece 478 0.52
16 Russian Federation 474 0.52
17 org 469 0.51
18 Mexico 463 0.51
19 Brazil 463 0.51
20 Belgium 447 0.49
21 Slovak Republic 401 0.44
22 France 374 0.41
23 Sweden 364 0.40
24 Romania 333 0.36
25 Canada 317 0.35
Sum 91,331 100.00

To top of page

Top 25 of 125 pathes , sorted by number of files

N pathes times %
1 /common/ 32,564 35.65
2 /avr_gra/ 14,994 16.42
3 / 10,589 11.59
4 /avr_en/beginner/ 3,550 3.89
5 /avr_de/ 2,856 3.13
6 /avr_en/ 2,755 3.02
7 /avr_de/beginner/ 2,639 2.89
8 /avr_en/calc/ 2,092 2.29
9 /avr_de/rechnen/ 1,863 2.04
10 /avr_de/stepper/ 1,501 1.64
11 /avr_de/fcount/ 1,500 1.64
12 /avr_en/source/ 1,329 1.46
13 /avr_de/praesentation/ 1,021 1.12
14 /avr_de/quellen/ 1,013 1.11
15 /avr_en/keypad/ 872 0.95
16 /avr_en/stepper/ 776 0.85
/avr_de/rechteckgen/
17 732 0.80
bilder/
18 /gavrasm/ 637 0.70
19 /avr_en/signalgen/pics/ 628 0.69
20 /avr_de/keypad/ 604 0.66
21 /avr_de/zeitschleifen/ 592 0.65
22 /avr_de/interrupts/ 391 0.43
23 /akkuload/ 376 0.41
24 /gavrasm/v21/ 307 0.34
25 /privat/katomic/ 301 0.33
Sum 91,331 100.00

To top of page

Top 25 of 125 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 184,266 18.32
2 /avr_gra/ 116,575 11.59
3 /avr_de/intro/pdf/ 90,267 8.98
4 / 60,387 6.00
5 /avr_de/fcount/ 56,098 5.58
6 /avr_de/ 44,083 4.38
7 /avr_en/ 38,592 3.84
8 /avr_de/stepper/ 37,984 3.78
9 /avr_en/beginner/ 30,255 3.01
10 /avr_de/beginner/ 25,495 2.54
11 /gavrasm/v21/ 23,621 2.35
12 /weblox_de/ 22,257 2.21
13 /weblox_en/ 19,985 1.99
/avr_de/rechteckgen/
14 19,779 1.97
bilder/
15 /avr_en/stepper/ 19,303 1.92
16 /avr_en/calc/ 17,389 1.73
17 /avr_de/rechnen/ 17,087 1.70
18 /avr_en/signalgen/pics/ 17,013 1.69
19 /common/ 15,667 1.56
20 /privat/magloop/ 13,023 1.29
21 /avr_de/rechteckgen/ 11,525 1.15
22 /avr_de/intro/ppt/ 10,995 1.09
23 /avr_en/signalgen/ 9,802 0.97
24 /akkuload/ 8,920 0.89
25 /avr_en/keypad/ 6,858 0.68
Sum 1,005,642 100.00

To top of page

Top 25 of 1397 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,740 5.19
2 /avr_gra/RingLogo.jpg 2,510 2.75
/common/knowhow.
3 2,126 2.33
gif
4 /common/akkuload.gif 2,117 2.32
5 /common/app.gif 2,115 2.32
6 /common/clock.gif 2,107 2.31
/common/download.
7 2,107 2.31
gif
8 /common/beginner.gif 2,106 2.31
9 /avr_gra/stk_lcd.jpg 2,104 2.30
10 /common/adc.gif 2,101 2.30
11 /common/keyb.gif 2,100 2.30
/common/gavrasmw.
12 2,095 2.29
gif
13 /common/example.gif 2,093 2.29
14 /common/hardware.gif 2,092 2.29
15 /common/r2r.gif 2,092 2.29
16 /common/gavrasm.gif 2,091 2.29
17 /common/calc.gif 2,085 2.28
18 /index.html 1,416 1.55
19 /avr_en/index.html 1,254 1.37
20 /avr_de/index.html 1,177 1.29
21 /avr_2313.gif 1,100 1.20
22 /dg4fac.gif 1,091 1.19
23 /avr-asm-tutorial.gif 1,087 1.19
24 /common/tn13.gif 1,047 1.15
25 /common/ints.gif 1,046 1.15
Sum 91,331 100.00

To top of page

Top 25 of 1397 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 62,944 6.26
2 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 38,450 3.82
3 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 32,153 3.20
4 /avr_de/index.html 26,566 2.64
/avr_de/praesentation/Teil_5b_Beispiel01_02.
5 26,165 2.60
pdf
6 /avr_en/index.html 25,661 2.55
7 /avr_2313.gif 19,768 1.97
8 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 17,509 1.74
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 17,457 1.74
10 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 15,052 1.50
11 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 13,041 1.30
12 /dg4fac.gif 11,758 1.17
13 /avr_de/fcount/dscf0004.jpg 11,051 1.10
14 /avr_gra/r2r_hardware.jpg 10,052 1.00
15 /avr_gra/pwm_simul.jpg 9,911 0.99
16 /avr_de/fcount/dscf0005.jpg 9,567 0.95
17 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 9,540 0.95
18 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 9,500 0.94
19 /avr_de/stepper/stepper_v1.gif 9,434 0.94
20 /favicon.ico 9,340 0.93
21 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 9,118 0.91
22 /avr_de/fcount/dscf0001.jpg 9,022 0.90
23 /avr_en/signalgen/pics/rectgen_wiring.jpg 7,780 0.77
24 /index.html 7,482 0.74
25 /avr_gra/stk_lcd.jpg 7,380 0.73
Sum 1,005,642 100.00

To top of page

Top 25 of 424 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,416 7.33
2 /avr_en/index.html 1,254 6.49
3 /avr_de/index.html 1,177 6.09
4 /avr_en/beginner/index.html 619 3.21
5 /avr_en/beginner/LEFT.html 593 3.07
6 /avr_en/beginner/RIGHT.html 588 3.04
7 /avr_de/beginner/index.html 402 2.08
8 /avr_de/beginner/links.html 388 2.01
9 /avr_de/beginner/rechts.html 380 1.97
/avr_en/beginner/HARDWARE.
10 239 1.24
html
11 /avr_de/stepper/stepper.html 207 1.07
12 /avr_en/beginner/REGISTER.html 202 1.05
13 /avr_en/keypad/keyboard.html 192 0.99
14 /avr_en/AVR_DAC.html 185 0.96
15 /avr_de/beginner/hardware.html 181 0.94
16 /avr_en/beginner/JUMP.html 176 0.91
17 /avr_de/beginner/sprung.html 156 0.81
18 /avr_de/praesentation/index.html 153 0.79
19 /avr_en/beginner/TOOLS.html 153 0.79
20 /avr_de/beginner/register.html 150 0.78
21 /avr_de/avr_dac.html 149 0.77
22 /avr_de/apps.html 143 0.74
23 /avr_de/fcount/fcount_m8.html 136 0.70
24 /avr_en/calc/index.html 136 0.70
25 /avr_en/beginner/PORTS.html 136 0.70
Sum 19,312 100.00

To top of page

Top 25 of 424 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 26,566 10.64
2 /avr_en/index.html 25,661 10.28
3 /index.html 7,482 3.00
4 /gb_new.html 4,437 1.78
5 /avr_de/dcf77uhr.html 4,328 1.73
6 /avr_en/beginner/RIGHT.html 4,264 1.71
7 /avr_de/beginner/sprung.html 4,216 1.69
8 /avr_en/beginner/JUMP.html 4,134 1.66
9 /avr_en/keypad/keyboard.html 3,987 1.60
10 /avr_en/beginner/CALC.html 3,354 1.34
11 /avr_de/stepper/stepper.html 2,976 1.19
12 /avr_de/keypad/keyboard.html 2,760 1.11
13 /avr_en/beginner/LEFT.html 2,725 1.09
14 /avr_de/beginner/rechts.html 2,704 1.08
15 /avr_en/AVR_DAC.html 2,637 1.06
16 /avr_de/beginner/rechnen.html 2,619 1.05
/avr_de/rechteckgen/rectgen_m8.
17 2,596 1.04
html
18 /avr_de/beginner/pdetail.html 2,552 1.02
19 /avr_de/avr_dac.html 2,426 0.97
20 /avr_en/beginner/REGISTER.html 2,327 0.93
/avr_en/beginner/COMMANDS.
21 2,266 0.91
html
22 /avr_en/beginner/PDETAIL.html 2,184 0.87
23 /sitemap_de.html 2,177 0.87
24 /avr_en/signalgen/rectgen_m8.html 2,163 0.87
25 /avr_de/beginner/commands.html 2,134 0.85
Sum 249,635 100.00

To top of page

Top 25 of 313 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,510 19.11
2 /avr_gra/stk_lcd.jpg 2,104 16.02
3 /avr_gra/8515.jpg 520 3.96
4 /avr_gra/avr_isp.jpg 380 2.89
5 /avr_gra/exp_2313.jpg 372 2.83
6 /avr_gra/exp2313g.jpg 369 2.81
7 /avr_gra/r2r_wave.jpg 334 2.54
8 /avr_gra/r2r_sawtooth.jpg 306 2.33
9 /avr_gra/r2r_triangle.jpg 292 2.22
10 /avr_gra/r2r_sawtoothupperbound.jpg 291 2.22
11 /avr_gra/r2r_hardware.jpg 290 2.21
12 /avr_gra/r2r_sawtooth741.jpg 290 2.21
13 /avr_gra/r2r_upperbound.jpg 289 2.20
14 /avr_gra/AT90S8515.jpg 218 1.66
15 /avr_de/stepper/stepper_sm.jpg 209 1.59
16 /avr_de/stepper/kp4m4-001.jpg 204 1.55
17 /avr_de/stepper/supply.jpg 202 1.54
18 /avr_de/stepper/driver.jpg 198 1.51
19 /avr_gra/apps.jpg 197 1.50
20 /avr_gra/adc8conn.jpg 177 1.35
21 /akkuload/dscf0030s.jpg 175 1.33
22 /avr_gra/pwm_simul.jpg 174 1.32
/avr_de/rechteckgen/bilder/rectgen_280.
23 151 1.15
jpg
24 /avr_de/praesentation/zuendtester.jpg 138 1.05
25 /avr_de/fcount/fcount_sm.jpg 137 1.04
Sum 13,136 100.00

To top of page

Top 25 of 358 GIF-files , sorted by number of files

N GIF-files times %
/common/knowhow.
1 2,126 4.38
gif
2 /common/akkuload.gif 2,117 4.37
3 /common/app.gif 2,115 4.36
4 /common/clock.gif 2,107 4.35
/common/download.
5 2,107 4.35
gif
6 /common/beginner.gif 2,106 4.34
7 /common/adc.gif 2,101 4.33
8 /common/keyb.gif 2,100 4.33
/common/gavrasmw.
9 2,095 4.32
gif
10 /common/example.gif 2,093 4.32
11 /common/hardware.gif 2,092 4.31
12 /common/r2r.gif 2,092 4.31
13 /common/gavrasm.gif 2,091 4.31
14 /common/calc.gif 2,085 4.30
15 /avr_2313.gif 1,100 2.27
16 /dg4fac.gif 1,091 2.25
17 /avr-asm-tutorial.gif 1,087 2.24
18 /common/tn13.gif 1,047 2.16
19 /common/ints.gif 1,046 2.16
20 /common/delay.gif 1,044 2.15
21 /avr_gra/2313.gif 941 1.94
22 /avr_gra/exp2313.gif 399 0.82
23 /avr_gra/avr_isp.gif 376 0.78
24 /avr_gra/isp10pin.gif 369 0.76
25 /avr_gra/isp6pin.gif 369 0.76
Sum 48,488 100.00

To top of page

Top 25 of 163 entry pages , sorted by number of files

N entry pages times %


1 /index.html 696 16.47
2 /avr_en/index.html 487 11.52
3 /avr_de/index.html 372 8.80
4 /avr_en/beginner/index.html 208 4.92
5 /avr_de/stepper/stepper.html 116 2.74
6 /avr_de/beginner/index.html 105 2.48
7 /avr_en/AVR_DAC.html 102 2.41
8 /avr_de/avr_dac.html 87 2.06
9 /avr_de/fcount/fcount_m8.html 85 2.01
10 /avr_en/keypad/keyboard.html 75 1.77
/avr_de/rechteckgen/rectgen_m8.
11 69 1.63
html
12 /avr_en/beginner/HARDWARE.html 64 1.51
13 /avr_de/keypad/keyboard.html 60 1.42
14 /avr_de/beginner/hardware.html 54 1.28
15 /avr_en/AVR_ADC500.html 53 1.25
16 /avr_de/intro/index.html 51 1.21
17 /avr_en/signalgen/rectgen_m8.html 49 1.16
18 /avr_en/stepper/stepper.html 45 1.06
19 /avr_de/beginner/pdetail.html 45 1.06
20 /akkuload/de/index.html 42 0.99
21 /avr_de/rechnen/konversion.html 41 0.97
22 /gb_new.html 35 0.83
23 /avr_de/rechnen/multiplikation.html 33 0.78
24 /avr_en/beginner/REGISTER.html 32 0.76
25 /avr_en/beginner/SRAM.html 31 0.73
Sum 4,226 100.00

To top of page

Top 25 of 207 cheat pages , sorted by number of files

N cheat pages times %


1 829 15.05
2 /index.html 411 7.46
3 /avr_en/index.html 401 7.28
4 /avr_de/index.html 319 5.79
5 /avr_en/beginner/RIGHT.html 148 2.69
6 /avr_de/stepper/stepper.html 118 2.14
7 /avr_en/keypad/keyboard.html 101 1.83
8 /avr_en/AVR_DAC.html 101 1.83
9 /avr_de/avr_dac.html 92 1.67
10 /avr_en/beginner/HARDWARE.html 86 1.56
11 /avr_de/fcount/fcount_m8.html 81 1.47
12 /avr_de/keypad/keyboard.html 77 1.40
13 /avr_de/beginner/rechts.html 69 1.25
14 /avr_de/beginner/hardware.html 67 1.22
/avr_de/rechteckgen/rectgen_m8.
15 60 1.09
html
16 /avr_en/AVR_ADC500.html 57 1.03
17 /avr_de/praesentation/index.html 54 0.98
18 /akkuload/de/index.html 54 0.98
19 /avr_en/signalgen/rectgen_m8.html 50 0.91
20 /avr_de/beginner/pdetail.html 50 0.91
21 /avr_en/stepper/stepper.html 50 0.91
22 /avr_en/beginner/REGISTER.html 49 0.89
23 /avr_de/beginner/sprung.html 47 0.85
24 /avr_en/beginner/SRAM.html 47 0.85
25 /avr_de/lcd4_500.html 46 0.83
Sum 5,510 100.00

To top of page

Top 25 of 187 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,409 14.64
2 /avr_en/beginner/index.html 1,056 10.97
3 /avr_de/beginner/index.html 653 6.79
4 / 651 6.77
5 /avr_en/index.html 558 5.80
6 /avr_en/beginner/RIGHT.html 525 5.46
7 /avr_en/ 520 5.40
8 /avr_de/beginner/rechts.html 390 4.05
9 /sitemap_de.html 326 3.39
10 /avr_en/beginner/LEFT.html 322 3.35
11 /sitemap_en.html 294 3.06
12 /avr_de/beginner/links.html 211 2.19
13 /avr_de/apps.html 162 1.68
14 /avr_de/ 151 1.57
15 /weblox_en/index.html 148 1.54
16 /weblox_de/index.html 148 1.54
17 /index.html 131 1.36
18 /avr_en/calc/index.html 121 1.26
/avr_de/zeitschleifen/index.
19 119 1.24
html
20 /avr_de/interrupts/index.html 101 1.05
21 /avr_de/avr_tut.html 101 1.05
22 /weblox_en/ 74 0.77
23 /weblox_de/ 74 0.77
24 /avr_en/AVR_TUT.html 73 0.76
25 /avr_en/APPS.html 61 0.63
Sum 9,622 100.00

To top of page

Top 25 of 362 external referrers , sorted by number of files

N external referrers times %


1 - 5,321 85.18
2 http://www.webring.com/hub?ring=avr 38 0.61
3 http://www.mikrocontroller.net/articles/AVR 23 0.37
4 http://www.dg4fac.de/linksunten.html 20 0.32
5 http://de.wikipedia.org/wiki/R2R-Netzwerk 20 0.32
http://www.avrfreaks.net/index.php?
6 name=PNphpBB2&file=viewtopic&t=7067 19 0.30
3
7 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 18 0.29
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
8 17 0.27
kurs.htm
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
9 17 0.27
ESC_by1_bz0_bs0.html
10 http://www.rowalt.de/mc/avr/linksd.htm 14 0.22
11 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 14 0.22
12 http://avr-asm.tripod.com/ 13 0.21
13 http://www.dg4fac.de/rechtsunten.html 13 0.21
14 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 12 0.19
http://electrons.psychogenic.com/modules/arms/art/3/
15 AVRGCCProgrammingG 11 0.18
uide.php
http://www.avrfreaks.net/index.php?
16 name=PNphpBB2&file=viewtopic&t=3698 10 0.16
8
17 http://www.educypedia.be/electronics/avr.htm 10 0.16
18 http://attiny.com/avrlinks.htm 10 0.16
19 http://www.mikrocontroller.net/articles/Linksammlung 9 0.14
20 http://www.geoclub.de/viewtopic.php?f=57&t=29640&start=10 9 0.14
21 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 8 0.13
http://www.8051projects.net/out.php?link=http://www.avr-asm-tutorial.n
22 7 0.11
et/avr_en/AVR_DAC.html
23 http://circuit.lt/?section=sch&page=avr.isp.lpt 7 0.11
24 http://blackstrom.derschwarz.de/avr/avr/index.shtml 7 0.11
25 http://www.elportal.pl/ea/asm_avr_jezyk.html 7 0.11
Sum 6,247 100.00

To top of page

Top 25 of 116 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,470 45.09
2 http://www.google.com 616 18.90
3 http://www.google.co.in 97 2.98
4 http://www.google.at 86 2.64
5 http://www.google.nl 73 2.24
6 http://www.google.ch 57 1.75
7 http://www.google.co.uk 56 1.72
8 http://www.google.pl 52 1.60
9 http://www.google.ca 36 1.10
10 http://www.google.it 31 0.95
11 http://www.google.co.id 28 0.86
12 http://www.google.hu 27 0.83
13 http://www.google.se 27 0.83
http://www.google.com.
14 26 0.80
au
15 http://www.google.cz 26 0.80
16 http://www.google.fi 25 0.77
17 http://www.google.bg 23 0.71
18 http://www.google.ro 21 0.64
19 http://search.yahoo.com 21 0.64
http://www.google.com.
20 19 0.58
br
21 http://www.google.ru 18 0.55
22 http://www.google.no 18 0.55
http://www.google.com.
23 16 0.49
pk
24 http://www.google.gr 16 0.49
http://de.search.yahoo.
25 15 0.46
com
Sum 3,260 100.00

To top of page

Top 25 of 2172 search strings , sorted by number of files

N search strings times %


1 avr tutorial 84 2.58
2 avr assembler 65 1.99
3 avr 55 1.69
4 assembler 34 1.04
5 attiny13 33 1.01
6 avr programming 26 0.80
7 assembler tutorial 25 0.77
8 avr assembly 22 0.67
9 ATtiny13 19 0.58
10 atmega8 16 0.49
11 avr assembler tutorial 15 0.46
12 stk500 14 0.43
13 assembler commands 13 0.40
14 avr asm 13 0.40
Atmega168 assembler
15 13 0.40
examples
16 AVR 12 0.37
17 avr asm tutorial 11 0.34
18 avr keypad 10 0.31
19 atmega16 10 0.31
20 assembler avr 10 0.31
21 katomic 10 0.31
22 Assembler 9 0.28
23 gavrasm 8 0.25
24 atmel avr 8 0.25
25 avr programing 8 0.25
Sum 3,260 100.00

To top of page

Top 7 of 7 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 81,768 89.53
2 304 Not changed 8,606 9.42

http://www.avr-asm-tutorial.net/weblox_en/2008w51.html (1 of 2)1/20/2009 8:08:20 PM


Weblog statistic for http://www.avr-asm-tutorial.net

3 206 Partial information 596 0.65


4 404 File not found 188 0.21
5 301 Permanently moved 161 0.18
6 300 Multiple choices 7 0.01
7 403 Forbidden 5 0.01
Sum 91,331 100.00

To top of page

Top 25 of 74 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 55 29.26
2 /beginner_de.pdf 24 12.77
/_vti_bin/owssvr.dll?
3 6 3.19
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
4 6 3.19
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
5 6 3.19
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 6 3.19
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
7 /avr_de/intro/ppt/beispiel10_snd.wav 6 3.19
8 /MarkAny/Websafer/MaSiteInfo.ini 3 1.60
9 /avr_de/praesentation/favicon.ico 2 1.06
10 /avr_de/praesentation/favicon.gif 2 1.06
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
11 20la 2 1.06
nguage_files/LEFT.htm
12 /_vti_inf.html 2 1.06
13 /akkuload/akkulcd.asm 2 1.06
14 /akkuload/akkuload.asm 2 1.06
15 /avr_en/CONVERSION.html 2 1.06
16 /avr_en/MULTIPLICATION.html 2 1.06
17 /avr_en/RIGHT.html 2 1.06
18 /index_en.html 2 1.06
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
19 20la 1 0.53
nguage.files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
20 20la 1 0.53
nguage.files/JUMP.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
21 20la 1 0.53
nguage3_files/LEFT.htm
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
22 20la 1 0.53
nguage5_files/LEFT.htm
23 /beginner_de.pdf" 1 0.53
/_vti_bin/owssvr.dll?
24 1 0.53
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
25 1 0.53
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
Sum 188 100.00

To top of page

Top 25 of 117 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 49,844 54.58
2 Mozilla/4.0 32,546 35.64
3 Opera/9.62 2,159 2.36
4 Yanga 1,061 1.16
5 Opera/9.63 746 0.82
6 FDM 2.x 563 0.62
7 Opera/9.60 514 0.56
8 Opera/9.52 382 0.42
9 Opera/9.61 296 0.32
10 Opera/9.51 268 0.29
11 msnbot/1.1 244 0.27
Googlebot-
12 213 0.23
Image/1.0
13 Opera/9.50 197 0.22
14 Opera/9.25 179 0.20
15 Opera/9.21 169 0.19
16 Safari5525.27.1 165 0.18
17 msnbot-media/1.1 155 0.17
18 Java/1.6.0_04 147 0.16
19 Ocelli/1.4 139 0.15
20 Opera/10.00 120 0.13
21 Yandex/1.01.001 105 0.11
22 Opera/9.23 101 0.11
23 ichiro/3.0 98 0.11
24 Mozilla/4.5 95 0.10
25 Download Master 65 0.07
Sum 91,331 100.00

To top of page

Top 25 of 269 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 18,753 20.53
2 MSIE 7.0 16,584 18.16
3 MSIE 6.0 13,561 14.85
4 Firefox/3.0.5 9,555 10.46
5 Gecko 2,484 2.72
6 Firefox/2.0.0.18 2,165 2.37
7 Opera/9.62 2,159 2.36
8 unknown 2,091 2.29
9 Firefox/3.0.4 1,838 2.01
10 Firefox/3.0.1 1,211 1.33
11 FDM 1,195 1.31
12 Firefox/3.0.3 1,085 1.19
13 Slurp 1,079 1.18
14 Firefox/2.0.0.6 924 1.01
15 Firefox/3.0.5 877 0.96
16 Firefox/2.0.0.19 858 0.94
17 Firefox/2.0.0.20 783 0.86
18 Opera/9.63 746 0.82
19 FDM 2.x 563 0.62
20 Firefox/3.0 553 0.61
21 Opera/9.60 495 0.54
22 Googlebot/2.1 413 0.45
23 Firefox/2.0.0.17 405 0.44
24 Opera/9.52 382 0.42
25 Slurp/3.0 362 0.40
Sum 91,331 100.00

To top of page

Top 25 of 46 operating systems , sorted by number of files

N operating systems times %


1 Windows 38,777 42.46
2 Windows NT 5.1 29,690 32.51
3 unknown 6,725 7.36
4 Linux i686 5,269 5.77
5 Windows NT 6.0 4,505 4.93
6 Windows NT 5.0 1,833 2.01
7 Windows 98 725 0.79
8 Linux x86_64 709 0.78
9 Mac OS X 10.5 605 0.66
10 Mac OS X 10_5_5 493 0.54
11 Mac OS X 10_4_11 273 0.30
12 Windows NT 5.2 244 0.27
13 Mac OS X 207 0.23
14 Linux i686 154 0.17
15 Linux 134 0.15
16 Mac OS X 10_5_6 128 0.14
17 Mac OS X 10.4 122 0.13
18 Windows XP 5.1 120 0.13
19 Win16 105 0.11
20 Windows NT 6.1 73 0.08
21 Windows 6.0 60 0.07
Linux 2.6.22.19-0.1-
22 46 0.05
default
23 Windows NT5 44 0.05
24 Mac OS X 10_5_3 41 0.04
25 Linux ppc 38 0.04
Sum 91,331 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,932 3.21
2 01 2,381 2.61
3 02 1,135 1.24
4 03 1,094 1.20
5 04 1,224 1.34
6 05 1,307 1.43
7 06 1,462 1.60
8 07 1,866 2.04
9 08 3,852 4.22
10 09 3,734 4.09
11 10 3,720 4.07
12 11 5,116 5.60
13 12 4,470 4.89
14 13 5,223 5.72
15 14 4,752 5.20
16 15 4,575 5.01
17 16 5,006 5.48
18 17 5,816 6.37
19 18 4,597 5.03
20 19 6,011 6.58
21 20 5,987 6.56
22 21 5,619 6.15
23 22 5,287 5.79
24 23 4,165 4.56
Sum 91,331 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w51.html (2 of 2)1/20/2009 8:08:20 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w50

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 50

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5568 IPs and host names , sorted by number of files

N IPs and host names times %


1 91.37.247.13=p5B25F70D.dip.t-dialin.net 781 0.89
2 67.195.37.157=llf320058.crawl.yahoo.net 679 0.78
91.96.223.131=host-091-096-223-131.ewe-ip-backbone.
3 407 0.46
de
4 82.80.155.162=bzq-82-80-155-162.dsl.bezeqint.net 272 0.31
5 118.68.56.168=adsl-dynamic-pool-xxx.hcm.fpt.vn 244 0.28
6 92.73.171.235=dslb-092-073-171-235.pools.arcor-ip.net 230 0.26
7 65.55.212.136=(not found) 219 0.25
8 91.113.27.31=91-113-27-31.adsl.highway.telekom.at 209 0.24
9 78.188.32.132=dsl78.188-8324.ttnet.net.tr 195 0.22
10 93.135.240.110=pass-5d87f06e.pool.einsundeins.de 195 0.22
11 217.17.24.225=dhcp.225.24.17.217.teliko.net 193 0.22
12 80.134.121.38=p50867926.dip.t-dialin.net 192 0.22
13 81.182.84.21=dsl51B65415.pool.t-online.hu 190 0.22
14 88.79.152.114=mx.rtk.de 184 0.21
15 66.249.71.206=crawl-66-249-71-206.googlebot.com 180 0.21
16 88.73.137.174=dslb-088-073-137-174.pools.arcor-ip.net 178 0.20
17 79.213.221.204=p4FD5DDCC.dip.t-dialin.net 172 0.20
18 84.134.220.7=p5486DC07.dip.t-dialin.net 171 0.20
19 66.249.71.205=crawl-66-249-71-205.googlebot.com 168 0.19
20 66.249.71.207=crawl-66-249-71-207.googlebot.com 166 0.19
21 78.53.70.184=f053070184.adsl.alicedsl.de 158 0.18
22 74.59.12.201=modemcable201.12-59-74.mc.videotron.ca 157 0.18
23 88.65.100.17=dslb-088-065-100-017.pools.arcor-ip.net 157 0.18
24 62.157.204.67=(not found) 156 0.18
25 193.226.6.228=c4.campus.utcluj.ro 156 0.18
Sum 87,534 100.00

To top of page

Top 25 of 5568 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 91.37.247.13=p5B25F70D.dip.t-dialin.net 28,966 3.11
2 67.195.37.157=llf320058.crawl.yahoo.net 11,844 1.27
91.96.223.131=host-091-096-223-131.ewe-ip-backbone.
3 7,865 0.85
de
4 84.164.117.152=p54A47598.dip.t-dialin.net 7,337 0.79
5 134.28.38.197=pc97.et1.tu-harburg.de 6,812 0.73
6 213.31.11.24=eur-info24.infonet.com 6,540 0.70
7 91.113.27.31=91-113-27-31.adsl.highway.telekom.at 6,266 0.67
8 87.169.248.45=p57A9F82D.dip.t-dialin.net 6,261 0.67
9 92.205.40.110=port-92-205-40-110.dynamic.qsc.de 6,247 0.67
10 91.21.253.108=p5B15FD6C.dip.t-dialin.net 5,544 0.60
11 88.152.112.113=ip-88-152-112-113.unitymediagroup.de 5,426 0.58
12 65.55.212.136=(not found) 5,409 0.58
13 84.60.41.155=dslb-084-060-041-155.pools.arcor-ip.net 5,242 0.56
14 80.123.8.206=80-123-8-206.adsl.highway.telekom.at 5,174 0.56
15 92.196.114.176=port-92-196-114-176.dynamic.qsc.de 4,931 0.53
16 91.65.25.101=91-65-25-101-dynip.superkabel.de 4,754 0.51
17 84.61.65.99=dslb-084-061-065-099.pools.arcor-ip.net 4,622 0.50
18 84.133.190.145=p5485BE91.dip.t-dialin.net 4,612 0.50
19 217.17.24.225=dhcp.225.24.17.217.teliko.net 4,515 0.49
20 77.22.123.118=(not found) 4,158 0.45
21 217.194.34.103=inac.erlm.siemens.de 4,115 0.44
22 84.156.204.91=p549CCC5B.dip.t-dialin.net 3,978 0.43
23 80.134.121.38=p50867926.dip.t-dialin.net 3,868 0.42
24 88.72.45.164=dslb-088-072-045-164.pools.arcor-ip.net 3,841 0.41
25 79.217.230.171=p4FD9E6AB.dip.t-dialin.net 3,813 0.41
Sum 930,188 100.00

To top of page

Top 25 of 971 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.157=llf320058.crawl.yahoo.net 98 2.67
2 66.249.71.205=crawl-66-249-71-205.googlebot.com 85 2.32
3 66.249.71.206=crawl-66-249-71-206.googlebot.com 82 2.23
4 66.249.71.207=crawl-66-249-71-207.googlebot.com 76 2.07
5 193.47.80.44=crawl8.exabot.com 60 1.64
6 193.252.149.15=natcrawlbloc02.net.s1.fti.net 36 0.98
7 208.111.154.16=crawl2.nat.svl.searchme.com 34 0.93
8 66.235.124.3=crawler5003.ask.com 33 0.90
9 81.52.143.16=natcrawlbloc03.net.m1.fti.net 33 0.90
10 65.55.212.136=(not found) 32 0.87
11 77.22.18.102=(not found) 31 0.84
12 208.111.154.15=crawl1.nat.svl.searchme.com 31 0.84
13 81.52.143.15=natcrawlbloc01.net.m1.fti.net 29 0.79
14 81.52.143.26=natcrawlbloc05.net.m1.fti.net 27 0.74
15 88.131.106.16=(not found) 24 0.65
16 193.252.149.16=natcrawlbloc04.net.s1.fti.net 19 0.52
17 118.136.25.173=173.25.136.118.fast.net.id 17 0.46
18 75.101.227.34=ec2-75-101-227-34.compute-1.amazonaws.com 16 0.44
19 217.17.24.225=dhcp.225.24.17.217.teliko.net 13 0.35
20 74.6.22.90=llf520091.crawl.yahoo.net 13 0.35
213.112.94.102=c-665e70d5.022-15-73746f7.cust.bredbandsbolaget.
21 13 0.35
se
22 85.18.227.211=85-18-227-211.ip.fastwebnet.it 12 0.33
23 99.186.64.109=adsl-99-186-64-109.dsl.hstntx.sbcglobal.net 12 0.33
24 218.248.46.115=(not found) 12 0.33
25 124.115.1.62=(not found) 12 0.33
Sum 3,669 100.00

To top of page

Top 25 of 95 countries of origin , sorted by number of files

N countries of origin times %


1 net 28,478 32.53
2 Germany 17,549 20.05
3 (unresolved) 15,000 17.14
4 com 5,381 6.15
5 Austria 2,305 2.63
6 Poland 1,674 1.91
7 Netherlands 1,327 1.52
8 Switzerland 1,226 1.40
9 Hungary 1,031 1.18
10 Czech Republic 787 0.90
11 India 754 0.86
12 Italy 753 0.86
13 Mexico 711 0.81
14 Romania 666 0.76
15 Belgium 624 0.71
16 edu 616 0.70
17 United Kingdom 597 0.68
18 Greece 509 0.58
19 Lithuania 466 0.53
20 Indonesia 438 0.50
21 Canada 390 0.45
22 Sweden 366 0.42
23 France 360 0.41
24 Vietnam 350 0.40
25 Australia 341 0.39
Sum 87,534 100.00

To top of page

Top 25 of 125 pathes , sorted by number of files

N pathes times %
1 /common/ 31,284 35.74
2 /avr_gra/ 15,551 17.77
3 / 10,523 12.02
4 /avr_en/beginner/ 4,015 4.59
5 /avr_de/beginner/ 2,967 3.39
6 /avr_en/ 2,525 2.88
7 /avr_de/ 2,482 2.84
8 /avr_de/rechnen/ 1,614 1.84
9 /avr_en/calc/ 1,441 1.65
10 /avr_de/stepper/ 1,259 1.44
11 /avr_de/fcount/ 1,238 1.41
12 /avr_de/praesentation/ 990 1.13
13 /avr_de/quellen/ 851 0.97
14 /avr_en/keypad/ 843 0.96
15 /avr_en/source/ 786 0.90
16 /avr_de/zeitschleifen/ 690 0.79
17 /avr_en/stepper/ 685 0.78
/avr_de/rechteckgen/
18 639 0.73
bilder/
19 /avr_de/keypad/ 620 0.71
20 /gavrasm/ 562 0.64
21 /avr_en/signalgen/pics/ 550 0.63
22 /avr_de/interrupts/ 464 0.53
23 /privat/magloop/ 358 0.41
24 /akkuload/ 328 0.37
25 /cq-dl/teil1/ 269 0.31
Sum 87,534 100.00

To top of page

Top 25 of 125 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 175,731 18.89
2 /avr_gra/ 124,785 13.42
3 /avr_de/intro/pdf/ 90,915 9.77
4 / 56,732 6.10
5 /avr_de/fcount/ 48,557 5.22
6 /avr_de/ 40,502 4.35
7 /avr_en/ 36,932 3.97
8 /avr_de/stepper/ 35,672 3.83
9 /avr_en/beginner/ 34,610 3.72
10 /avr_de/beginner/ 27,575 2.96
11 /avr_en/stepper/ 18,004 1.94
12 /avr_de/intro/ppt/ 17,575 1.89
/avr_de/rechteckgen/
13 17,168 1.85
bilder/
14 /privat/magloop/ 16,293 1.75
15 /common/ 15,252 1.64
16 /avr_de/rechnen/ 14,733 1.58
17 /avr_en/signalgen/pics/ 14,273 1.53
18 /avr_en/calc/ 13,066 1.40
19 /gavrasm/v21/ 12,898 1.39
20 /avr_en/signalgen/ 10,875 1.17
21 /avr_de/rechteckgen/ 9,980 1.07
22 /akkuload/ 8,508 0.91
23 /weblox_de/ 7,360 0.79
24 /weblox_en/ 6,445 0.69
25 /avr_en/keypad/ 6,414 0.69
Sum 930,188 100.00

To top of page

Top 25 of 1387 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,939 5.64
2 /avr_gra/RingLogo.jpg 2,448 2.80
3 /common/akkuload.gif 2,036 2.33
/common/download.
4 2,035 2.32
gif
5 /common/app.gif 2,029 2.32
/common/knowhow.
6 2,025 2.31
gif
7 /common/gavrasm.gif 2,018 2.31
8 /common/example.gif 2,018 2.31
9 /common/clock.gif 2,017 2.30
10 /avr_gra/stk_lcd.jpg 2,016 2.30
/common/gavrasmw.
11 2,014 2.30
gif
12 /common/keyb.gif 2,012 2.30
13 /common/r2r.gif 2,012 2.30
14 /common/beginner.gif 2,011 2.30
15 /common/adc.gif 2,008 2.29
16 /common/calc.gif 2,000 2.28
17 /common/hardware.gif 1,999 2.28
18 /index.html 1,380 1.58
19 /avr_en/index.html 1,226 1.40
20 /avr_de/index.html 1,116 1.27
21 /avr_gra/2313.gif 1,111 1.27
22 /avr_2313.gif 1,090 1.25
23 /avr-asm-tutorial.gif 1,032 1.18
24 /dg4fac.gif 1,032 1.18
25 /common/delay.gif 1,021 1.17
Sum 87,534 100.00

To top of page

Top 25 of 1387 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 53,260 5.73
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 35,829 3.85
3 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 30,104 3.24
/avr_de/praesentation/Teil_5b_Beispiel01_02.
4 25,477 2.74
pdf
5 /avr_en/index.html 25,371 2.73
6 /avr_de/index.html 25,368 2.73
7 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 24,161 2.60
8 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 20,523 2.21
9 /avr_2313.gif 18,584 2.00
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 17,651 1.90
11 /avr_gra/pwm_simul.jpg 11,738 1.26
12 /dg4fac.gif 11,109 1.19
13 /avr_gra/r2r_hardware.jpg 10,718 1.15
14 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 10,120 1.09
15 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 9,989 1.07
16 /favicon.ico 9,731 1.05
17 /avr_de/fcount/dscf0004.jpg 9,524 1.02
18 /avr_de/stepper/stepper_v1.gif 8,745 0.94
19 /avr_de/intro/pdf/Teil1_Prozessor.pdf 8,588 0.92
20 /avr_de/fcount/dscf0005.jpg 8,206 0.88
21 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 7,980 0.86
22 /avr_gra/2313.gif 7,880 0.85
23 /avr_de/intro/ppt/AVREinfuehrung_ppt.zip 7,848 0.84
24 /avr_de/fcount/dscf0001.jpg 7,821 0.84
25 /index.html 7,344 0.79
Sum 930,188 100.00

To top of page

Top 25 of 417 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,380 7.43
2 /avr_en/index.html 1,226 6.60
3 /avr_de/index.html 1,116 6.01
4 /avr_en/beginner/index.html 705 3.80
5 /avr_en/beginner/LEFT.html 697 3.75
6 /avr_en/beginner/RIGHT.html 692 3.73
7 /avr_de/beginner/index.html 480 2.59
8 /avr_de/beginner/links.html 461 2.48
9 /avr_de/beginner/rechts.html 460 2.48
/avr_en/beginner/HARDWARE.
10 266 1.43
html
11 /avr_en/beginner/REGISTER.html 226 1.22
12 /avr_en/beginner/JUMP.html 194 1.04
13 /avr_en/AVR_DAC.html 190 1.02
14 /avr_de/stepper/stepper.html 175 0.94
15 /avr_en/keypad/keyboard.html 172 0.93
16 /avr_de/beginner/register.html 169 0.91
17 /avr_de/beginner/hardware.html 162 0.87
18 /avr_en/beginner/TOOLS.html 156 0.84
19 /avr_en/beginner/PORTS.html 155 0.83
20 /avr_de/praesentation/index.html 154 0.83
21 /avr_de/beginner/werkzeuge.html 154 0.83
22 /avr_en/beginner/SRAM.html 149 0.80
23 /avr_de/beginner/sprung.html 148 0.80
24 /avr_en/beginner/CALC.html 144 0.78
25 /avr_de/zeitschleifen/index.html 143 0.77
Sum 18,567 100.00

To top of page

Top 25 of 417 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 25,371 11.74
2 /avr_de/index.html 25,368 11.74
3 /index.html 7,344 3.40
4 /avr_en/beginner/RIGHT.html 5,080 2.35
5 /avr_en/beginner/JUMP.html 4,665 2.16
6 /avr_de/beginner/sprung.html 4,030 1.86
7 /gb_new.html 3,760 1.74
8 /avr_en/keypad/keyboard.html 3,606 1.67
9 /avr_en/beginner/CALC.html 3,601 1.67
10 /avr_de/dcf77uhr.html 3,564 1.65
11 /avr_en/beginner/LEFT.html 3,255 1.51
12 /avr_de/beginner/rechts.html 3,168 1.47
13 /avr_de/beginner/rechnen.html 2,889 1.34
14 /avr_de/stepper/stepper.html 2,784 1.29
15 /avr_en/AVR_DAC.html 2,779 1.29
/avr_en/beginner/COMMANDS.
16 2,750 1.27
html
17 /avr_de/keypad/keyboard.html 2,728 1.26
18 /avr_en/beginner/REGISTER.html 2,657 1.23
19 /avr_de/avr_dac.html 2,484 1.15
/avr_de/rechteckgen/rectgen_m8.
20 2,332 1.08
html
21 /avr_en/beginner/PDETAIL.html 2,285 1.06
22 /avr_de/beginner/pdetail.html 2,262 1.05
23 /avr_de/beginner/commands.html 2,222 1.03
24 /sitemap_de.html 2,100 0.97
25 /avr_de/beginner/links.html 2,055 0.95
Sum 216,154 100.00

To top of page

Top 25 of 362 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,448 18.86
2 /avr_gra/stk_lcd.jpg 2,016 15.53
3 /avr_gra/8515.jpg 474 3.65
4 /avr_gra/avr_isp.jpg 390 3.01
5 /avr_gra/exp_2313.jpg 387 2.98
6 /avr_gra/exp2313g.jpg 387 2.98
7 /avr_gra/r2r_wave.jpg 331 2.55
8 /avr_gra/r2r_sawtooth.jpg 316 2.43
9 /avr_gra/r2r_hardware.jpg 302 2.33
10 /avr_gra/r2r_triangle.jpg 301 2.32
11 /avr_gra/r2r_sawtooth741.jpg 300 2.31
12 /avr_gra/r2r_upperbound.jpg 298 2.30
13 /avr_gra/r2r_sawtoothupperbound.jpg 296 2.28
14 /avr_gra/AT90S8515.jpg 238 1.83
15 /avr_gra/pwm_simul.jpg 210 1.62
16 /avr_gra/adc8conn.jpg 209 1.61
17 /avr_gra/apps.jpg 181 1.39
18 /avr_de/stepper/stepper_sm.jpg 180 1.39
19 /avr_de/stepper/supply.jpg 171 1.32
20 /avr_de/stepper/kp4m4-001.jpg 171 1.32
21 /avr_de/stepper/driver.jpg 168 1.29
22 /akkuload/dscf0030s.jpg 158 1.22
23 /avr_de/praesentation/zuendtester.jpg 138 1.06
/avr_de/rechteckgen/bilder/rectgen_280.
24 135 1.04
jpg
25 /avr_en/signalgen/pics/rectgen_280.jpg 125 0.96
Sum 12,978 100.00

To top of page

Top 25 of 289 GIF-files , sorted by number of files

N GIF-files times %
1 /common/akkuload.gif 2,036 4.36
/common/download.
2 2,035 4.36
gif
3 /common/app.gif 2,029 4.34
/common/knowhow.
4 2,025 4.33
gif
5 /common/gavrasm.gif 2,018 4.32
6 /common/example.gif 2,018 4.32
7 /common/clock.gif 2,017 4.32
/common/gavrasmw.
8 2,014 4.31
gif
9 /common/keyb.gif 2,012 4.31
10 /common/r2r.gif 2,012 4.31
11 /common/beginner.gif 2,011 4.30
12 /common/adc.gif 2,008 4.30
13 /common/calc.gif 2,000 4.28
14 /common/hardware.gif 1,999 4.28
15 /avr_gra/2313.gif 1,111 2.38
16 /avr_2313.gif 1,090 2.33
17 /avr-asm-tutorial.gif 1,032 2.21
18 /dg4fac.gif 1,032 2.21
19 /common/delay.gif 1,021 2.19
20 /common/ints.gif 1,021 2.19
21 /common/tn13.gif 1,008 2.16
22 /avr_gra/exp2313.gif 402 0.86
23 /avr_gra/avr_isp.gif 396 0.85
24 /avr_gra/isp10pin.gif 388 0.83
25 /avr_gra/isp6pin.gif 387 0.83
Sum 46,725 100.00

To top of page

Top 25 of 165 entry pages , sorted by number of files

N entry pages times %


1 /index.html 678 16.02
2 /avr_en/index.html 478 11.30
3 /avr_de/index.html 381 9.00
4 /avr_en/beginner/index.html 216 5.11
5 /avr_de/beginner/index.html 132 3.12
6 /avr_en/AVR_DAC.html 124 2.93
7 /avr_de/stepper/stepper.html 101 2.39
8 /avr_de/avr_dac.html 82 1.94
9 /avr_en/beginner/HARDWARE.html 70 1.65
10 /avr_de/fcount/fcount_m8.html 70 1.65
11 /avr_en/keypad/keyboard.html 64 1.51
12 /avr_de/intro/index.html 63 1.49
13 /avr_en/stepper/stepper.html 52 1.23
/avr_de/rechteckgen/rectgen_m8.
14 52 1.23
html
15 /avr_de/keypad/keyboard.html 51 1.21
16 /avr_de/rechnen/konversion.html 49 1.16
17 /avr_en/AVR_ADC500.html 48 1.13
18 /avr_en/signalgen/rectgen_m8.html 41 0.97
19 /avr_de/rechnen/multiplikation.html 40 0.95
20 /avr_de/beginner/werkzeuge.html 33 0.78
21 /avr_en/beginner/SRAM.html 32 0.76
22 /avr_en/beginner/REGISTER.html 32 0.76
23 /gb_new.html 32 0.76
24 /avr_en/beginner/JUMP.html 32 0.76
25 /avr_de/beginner/hardware.html 32 0.76
Sum 4,231 100.00

To top of page

Top 25 of 203 cheat pages , sorted by number of files

N cheat pages times %


1 839 15.07
2 /index.html 423 7.60
3 /avr_en/index.html 378 6.79
4 /avr_de/index.html 311 5.59
5 /avr_en/beginner/RIGHT.html 162 2.91
6 /avr_en/AVR_DAC.html 133 2.39
7 /avr_de/stepper/stepper.html 104 1.87
8 /avr_de/beginner/rechts.html 92 1.65
9 /avr_en/keypad/keyboard.html 91 1.63
10 /avr_en/beginner/HARDWARE.html 91 1.63
11 /avr_de/avr_dac.html 81 1.45
12 /avr_en/beginner/REGISTER.html 73 1.31
13 /avr_de/fcount/fcount_m8.html 68 1.22
14 /avr_en/AVR_ADC500.html 64 1.15
15 /avr_en/beginner/JUMP.html 62 1.11
16 /avr_de/keypad/keyboard.html 60 1.08
17 /avr_de/beginner/sprung.html 59 1.06
/avr_de/rechteckgen/rectgen_m8.
18 55 0.99
html
19 /akkuload/de/index.html 53 0.95
20 /avr_de/intro/index.html 51 0.92
21 /avr_en/stepper/stepper.html 51 0.92
22 /avr_de/beginner/rechnen.html 47 0.84
23 /avr_de/beginner/werkzeuge.html 46 0.83
24 /avr_de/praesentation/index.html 46 0.83
25 /avr_en/beginner/SRAM.html 46 0.83
Sum 5,568 100.00

To top of page

Top 25 of 164 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,590 16.33
2 /avr_en/beginner/index.html 1,209 12.42
3 /avr_de/beginner/index.html 813 8.35
4 /avr_en/index.html 580 5.96
5 /avr_en/beginner/RIGHT.html 571 5.86
6 / 548 5.63
7 /avr_en/ 495 5.08
8 /avr_en/beginner/LEFT.html 427 4.39
9 /avr_de/beginner/rechts.html 425 4.36
10 /avr_de/beginner/links.html 348 3.57
11 /sitemap_de.html 181 1.86
12 /avr_de/apps.html 153 1.57
13 /avr_de/zeitschleifen/index.html 148 1.52
14 /avr_de/interrupts/index.html 140 1.44
15 /index.html 123 1.26
16 /avr_de/avr_tut.html 103 1.06
17 /sitemap_en.html 102 1.05
18 /avr_en/AVR_TUT.html 97 1.00
19 /avr_en/calc/index.html 80 0.82
20 /avr_de/ 76 0.78
21 /weblox_de/index.html 74 0.76
22 /avr_de/beginner/commands.html 72 0.74
23 /weblox_en/index.html 72 0.74
/avr_en/beginner/COMMANDS.
24 69 0.71
html
25 /avr_en/APPS.html 64 0.66
Sum 9,737 100.00

To top of page

Top 25 of 355 external referrers , sorted by number of files

N external referrers times %


1 - 4,383 82.46
2 http://www.mikrocontroller.net/articles/AVR 40 0.75
3 http://www.webring.com/hub?ring=avr 30 0.56
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
4 23 0.43
kurs.htm
5 http://avr-asm.tripod.com/ 20 0.38
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
6 19 0.36
ESC_by1_bz0_bs0.html
7 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 19 0.36
8 http://www.rowalt.de/mc/avr/linksd.htm 17 0.32
9 http://www.educypedia.be/electronics/avr.htm 17 0.32
10 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 17 0.32
11 http://www.dg4fac.de/rechtsunten.html 15 0.28
12 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 14 0.26
13 http://de.wikipedia.org/wiki/R2R-Netzwerk 13 0.24
14 http://www.mikrocontroller.net/articles/Linksammlung 13 0.24
http://www.avrfreaks.net/index.php?
15 name=PNphpBB2&file=viewtopic&t=7067 12 0.23
3
16 http://www.serasidis.gr/link.htm 10 0.19
17 http://www.heni-online.de/java/atomicplay_js.php 10 0.19
18 http://frank.bol.ucla.edu/avr.htm 10 0.19
19 http://www.dg4fac.de/linksunten.html 10 0.19
http://electrons.psychogenic.com/modules/arms/art/3/
20 AVRGCCProgrammingG 9 0.17
uide.php
21 http://learn-avr.blogspot.com/2008/10/blog-post_9078.html 8 0.15
22 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 8 0.15
23 http://avr-asm.tripod.com/index.html 7 0.13
24 http://circuit.lt/?section=sch&page=avr.isp.lpt 7 0.13
25 http://www.bergstrasse.de/darc-f02/einladung.pdf 7 0.13
Sum 5,315 100.00

To top of page

Top 25 of 127 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,395 42.22
2 http://www.google.com 661 20.01
3 http://www.google.co.in 116 3.51
4 http://www.google.at 98 2.97
5 http://www.google.co.uk 63 1.91
6 http://www.google.ch 62 1.88
7 http://www.google.ca 56 1.69
8 http://www.google.nl 56 1.69
9 http://www.google.pl 49 1.48
10 http://www.google.fi 35 1.06
11 http://search.live.com 34 1.03
12 http://www.google.hu 32 0.97
13 http://www.google.ro 31 0.94
14 http://www.google.cz 25 0.76
15 http://www.google.co.id 25 0.76
16 http://search.yahoo.com 24 0.73
17 http://www.google.it 24 0.73
18 http://www.google.com.au 22 0.67
19 http://www.google.be 22 0.67
20 http://www.google.com.br 22 0.67
http://www.google.com.
21 20 0.61
mx
22 http://www.google.gr 19 0.58
23 http://www.google.fr 19 0.58
24 http://www.google.se 18 0.54
25 http://www.google.pt 17 0.51
Sum 3,304 100.00

To top of page

Top 25 of 2192 search strings , sorted by number of files

N search strings times %


1 avr tutorial 85 2.57
2 avr 45 1.36
3 attiny13 43 1.30
4 avr programming 42 1.27
5 avr assembler 42 1.27
6 avr assembly 35 1.06
7 assembler 29 0.88
8 ATtiny13 21 0.64
avr assembler
9 17 0.51
tutorial
10 assembler tutorial 17 0.51
11 avr asm 16 0.48
12 atmega8 14 0.42
13 AVR 13 0.39
assembler
14 13 0.39
commands
15 avr registers 13 0.39
16 stk500 13 0.39
17 avr assembly tutorial 12 0.36
18 avr tutorials 11 0.33
19 STK500 11 0.33
20 assembler avr 11 0.33
21 avr asm tutorial 10 0.30
22 AVR tutorial 10 0.30
23 avr programing 9 0.27
24 MCUCR 9 0.27
25 wavrasm 8 0.24
Sum 3,304 100.00

To top of page

Top 8 of 8 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 79,401 90.71
2 304 Not changed 7,342 8.39
3 206 Partial information 457 0.52
4 404 File not found 186 0.21
5 301 Permanently moved 129 0.15
6 300 Multiple choices 8 0.01
7 403 Forbidden 6 0.01

http://www.avr-asm-tutorial.net/weblox_en/2008w50.html (1 of 2)1/20/2009 8:08:43 PM


Weblog statistic for http://www.avr-asm-tutorial.net

8 xxx Unknown error 5 0.01


Sum 87,534 100.00

To top of page

Top 25 of 55 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 47 25.27
2 /MarkAny/Websafer/MaSiteInfo.ini 29 15.59
3 /avr_de/intro/ppt/beispiel10_snd.wav 15 8.06
4 /beginner_de.pdf 13 6.99
5 /avr_de/praesentation/favicon.ico 6 3.23
6 /avr_de/praesentation/favicon.gif 6 3.23
/_vti_bin/owssvr.dll?
7 4 2.15
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
8 4 2.15
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
9 4 2.15
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
10 4 2.15
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
11 /sitemap.xml 3 1.61
12 /_vti_inf.html 2 1.08
13 /gb 2 1.08
/privat/magloop/errors.php?error=http://flowskatepark.org/WebCalendar-
14 2 1.08
1.0.4/includes/safe1.txt??
/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/includes/
15 2 1.08
safe1.txt??
/privat/errors.php?error=http://flowskatepark.org/WebCalendar-1.0.4/in
16 2 1.08
cludes/safe1.txt??
/avr_de/praesentation/sourcecode/errors.php?error=http://flowskatepark
17 2 1.08
.org/WebCalendar-1.0.4/includes/safe1.txt??
/avr_de/praesentation/errors.php?error=http://flowskatepark.org/WebCal
18 2 1.08
endar-1.0.4/includes/safe1.txt??
19 /avr_en/html 1 0.54
/avr_en/keypad/keyboard.html/include/global.php?pfad=http://v13.sitebu
20 1 0.54
rg.com/ed.txt??
21 /include/global.php?pfad=http://v13.siteburg.com/ed.txt?? 1 0.54
/avr_en/keypad/include/global.php?pfad=http://v13.siteburg.com/ed.txt?
22 1 0.54
?
/avr_en/beginner/HARDWARE.html/include/global.php?pfad=http://v13.site
23 1 0.54
burg.com/ed.txt??
/avr_en/beginner/include/global.php?pfad=http://v13.siteburg.com/ed.tx
24 1 0.54
t??
/avr_en/keypad/keyboard.html/include/global.php?pfad=http://v13.sitebu
25 1 0.54
rg.com/ed.txt%0D??
Sum 186 100.00

To top of page

Top 25 of 119 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 48,795 55.74
2 Mozilla/4.0 30,486 34.83
3 Opera/9.62 2,347 2.68
4 Xaldon 756 0.86
5 Opera/9.51 662 0.76
6 Opera/9.61 491 0.56
7 Mozilla/4.5 412 0.47
8 Opera/9.52 392 0.45
9 Opera/9.60 391 0.45
10 msnbot/1.1 327 0.37
11 Googlebot-Image/1.0 244 0.28
12 msnbot-media/1.0 219 0.25
13 Safari/5525.27.1 175 0.20
14 Opera/9.50 166 0.19
15 Opera/9.21 161 0.18
16 Opera/9.27 131 0.15
17 - 120 0.14
18 FDM 2.x 108 0.12
SonyEricssonP1i/
19 77 0.09
R100
20 msnbot-media/1.1 75 0.09
21 Yandex/1.01.001 50 0.06
22 CFNetwork/221.5 50 0.06
23 Opera/9.25 50 0.06
24 Nokia6030/2.0 47 0.05
25 Mozilla/3.01 43 0.05
Sum 87,534 100.00

To top of page

Top 25 of 267 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 28,003 31.99
2 MSIE 7.0 15,428 17.63
3 MSIE 6.0 12,350 14.11
4 Firefox/2.0.0.18 3,118 3.56
5 Firefox/3.0.4 2,495 2.85
6 Opera/9.62 2,341 2.67
7 Gecko 2,280 2.60
8 Firefox/3.0.3 1,707 1.95
9 Firefox/3.0.1 1,631 1.86
10 Slurp 1,199 1.37
11 FDM 897 1.02
12 unknown 837 0.96
13 WebSpider 2.7.b6 756 0.86
14 Firefox/3.0 725 0.83
15 Opera/9.51 662 0.76
16 Opera/9.61 491 0.56
17 HTTrack 3.0x 412 0.47
18 Firefox/2.0.0.14 395 0.45
19 Opera/9.52 392 0.45
20 Opera/9.60 391 0.45
21 MSIE 5.0 366 0.42
22 Firefox/2.0.0.16 357 0.41
23 Slurp/3.0 337 0.38
24 msnbot/1.1 327 0.37
25 Avant Browser 301 0.34
Sum 87,534 100.00

To top of page

Top 25 of 41 operating systems , sorted by number of files

N operating systems times %


1 Windows 39,274 44.87
2 Windows NT 5.1 27,032 30.88
3 unknown 5,463 6.24
4 Windows NT 6.0 4,673 5.34
5 Linux i686 4,582 5.23
6 Windows NT 5.0 1,421 1.62
7 Windows 98 1,114 1.27
8 Linux x86_64 848 0.97
9 Mac OS X 10_5_5 692 0.79
10 Windows NT 5.2 401 0.46
11 Mac OS X 10.5 333 0.38
12 Mac OS X 263 0.30
13 Windows NT 4.0 255 0.29
14 Windows XP 5.1 195 0.22
15 Linux 182 0.21
16 Linux i686 171 0.20
Mac OS X
17 121 0.14
10_4_11
18 Mac OS X Mach-O 87 0.10
19 Mac OS X 10.4 85 0.10
20 Windows 6.0 62 0.07
21 Win16 52 0.06
22 Windows NT5 41 0.05
23 Windows 95 36 0.04
24 Windows CE 32 0.04
25 Mac OS X 10_5_4 24 0.03
Sum 87,534 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,458 2.81
2 01 2,552 2.92
3 02 1,308 1.49
4 03 1,255 1.43
5 04 1,301 1.49
6 05 1,135 1.30
7 06 1,485 1.70
8 07 1,803 2.06
9 08 2,541 2.90
10 09 3,789 4.33
11 10 4,311 4.92
12 11 4,153 4.74
13 12 4,772 5.45
14 13 4,720 5.39
15 14 4,564 5.21
16 15 5,116 5.84
17 16 5,167 5.90
18 17 5,843 6.68
19 18 4,602 5.26
20 19 5,044 5.76
21 20 5,213 5.96
22 21 5,768 6.59
23 22 5,054 5.77
24 23 3,580 4.09
Sum 87,534 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w50.html (2 of 2)1/20/2009 8:08:43 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w49

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 49

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5978 IPs and host names , sorted by number of files

N IPs and host names times %


1 125.163.229.71=71.subnet125-163-229.speedy.telkom.net.id 810 0.86
2 128.119.91.226=culloden.ecs.umass.edu 686 0.72
125.163.229.120=120.subnet125-163-229.speedy.telkom.net.
3 611 0.65
id
4 91.205.124.9=(not found) 588 0.62
5 93.146.64.226=net-93-146-64-226.t2.dsl.vodafone.it 474 0.50
6 67.195.37.157=llf320058.crawl.yahoo.net 392 0.41
7 92.105.57.123=123-57.105-92.cust.bluewin.ch 357 0.38
8 93.221.114.88=p5DDD7258.dip.t-dialin.net 337 0.36
9 67.195.37.109=llf320031.crawl.yahoo.net 336 0.35
10 93.158.148.31=spider11.yandex.ru 309 0.33
11 85.181.177.189=e181177189.adsl.alicedsl.de 304 0.32
12 91.67.187.61=91-67-187-61-dynip.superkabel.de 303 0.32
13 88.65.109.83=dslb-088-065-109-083.pools.arcor-ip.net 278 0.29
14 81.15.165.7=prior.internet.radom.pl 274 0.29
15 91.21.245.47=p5B15F52F.dip.t-dialin.net 265 0.28
16 88.65.106.191=dslb-088-065-106-191.pools.arcor-ip.net 250 0.26
17 38.99.13.125=crawl-4.cuill.com 236 0.25
18 66.249.71.207=crawl-66-249-71-207.googlebot.com 218 0.23
19 66.249.71.206=crawl-66-249-71-206.googlebot.com 217 0.23
20 66.249.72.79=crawl-66-249-72-79.googlebot.com 211 0.22
21 84.178.90.17=p54B25A11.dip.t-dialin.net 207 0.22
22 66.249.71.205=crawl-66-249-71-205.googlebot.com 202 0.21
23 208.111.154.16=crawl2.nat.svl.searchme.com 189 0.20
24 84.115.14.174=chello084115014174.wrn.surfer.at 183 0.19
25 87.164.61.53=p57A43D35.dip.t-dialin.net 182 0.19
Sum 94,657 100.00

To top of page

Top 25 of 5978 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 125.163.229.71=71.subnet125-163-229.speedy.telkom.net.id 16,957 1.68
2 93.146.64.226=net-93-146-64-226.t2.dsl.vodafone.it 16,588 1.65
125.163.229.120=120.subnet125-163-229.speedy.telkom.net.
3 16,352 1.62
id
4 91.205.124.9=(not found) 15,843 1.57
5 84.61.88.54=dslb-084-061-088-054.pools.arcor-ip.net 13,602 1.35
6 85.178.152.20=e178152020.adsl.alicedsl.de 10,927 1.08
7 94.222.120.43=(not found) 9,335 0.93
8 65.55.212.136=(not found) 8,982 0.89
9 77.179.29.12=cotb-4db31d0c.pool.einsundeins.de 6,750 0.67
10 212.95.22.161=212095022161.public.telering.at 6,519 0.65
11 91.10.231.21=p5B0AE715.dip.t-dialin.net 6,292 0.62
12 77.119.114.249=77.119.114.249.wireless.dyn.drei.com 6,145 0.61
13 84.119.14.77=84-119-14-77.dynamic.xdsl-line.inode.at 6,133 0.61
14 93.221.114.88=p5DDD7258.dip.t-dialin.net 6,061 0.60
15 67.195.37.157=llf320058.crawl.yahoo.net 5,772 0.57
16 192.109.190.88=vproxy01.bmwgroup.com 5,674 0.56
17 88.73.189.225=dslb-088-073-189-225.pools.arcor-ip.net 4,942 0.49
18 213.189.138.226=mail.arfa.ch 4,838 0.48
19 67.195.37.109=llf320031.crawl.yahoo.net 4,783 0.47
20 84.143.240.209=p548FF0D1.dip.t-dialin.net 4,638 0.46
21 66.249.71.207=crawl-66-249-71-207.googlebot.com 4,207 0.42
22 217.199.92.108=217.199.92.108.jm-data.at 4,065 0.40
23 62.143.187.41=ip-62-143-187-41.unitymediagroup.de 3,776 0.37
24 84.164.176.6=p54A4B006.dip0.t-ipconnect.de 3,771 0.37
25 84.114.133.183=chello084114133183.16.15.vie.surfer.at 3,685 0.37
Sum 1,007,422 100.00

To top of page

Top 25 of 1021 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.157=llf320058.crawl.yahoo.net 77 2.07
2 66.249.71.207=crawl-66-249-71-207.googlebot.com 65 1.75
3 66.249.71.205=crawl-66-249-71-205.googlebot.com 63 1.69
4 208.111.154.16=crawl2.nat.svl.searchme.com 63 1.69
5 66.249.71.206=crawl-66-249-71-206.googlebot.com 57 1.53
6 208.111.154.15=crawl1.nat.svl.searchme.com 55 1.48
7 193.47.80.44=crawl8.exabot.com 49 1.32
8 88.131.106.16=(not found) 41 1.10
9 67.195.37.109=llf320031.crawl.yahoo.net 35 0.94
10 66.249.72.79=crawl-66-249-72-79.googlebot.com 35 0.94
11 38.99.13.125=crawl-4.cuill.com 30 0.81
12 77.22.18.102=(not found) 30 0.81
13 128.119.91.226=culloden.ecs.umass.edu 22 0.59
14 193.252.149.15=natcrawlbloc02.net.s1.fti.net 22 0.59
15 81.52.143.16=natcrawlbloc03.net.m1.fti.net 18 0.48
16 208.44.234.50=(not found) 18 0.48
65.55.209.164=msnbot-65-55-209-164.search.msn.
17 18 0.48
com
18 81.52.143.26=natcrawlbloc05.net.m1.fti.net 17 0.46
65.55.209.165=msnbot-65-55-209-165.search.msn.
19 17 0.46
com
20 81.52.143.15=natcrawlbloc01.net.m1.fti.net 15 0.40
21 202.160.178.127=lj910246.crawl.yahoo.net 15 0.40
22 194.39.218.10=http-v.fe.bosch.de 14 0.38
65.55.230.207=msnbot-65-55-230-207.search.msn.
23 13 0.35
com
24 203.23.220.27=(not found) 13 0.35
25 208.111.154.27=v27.nat.svl.searchme.com 13 0.35
Sum 3,718 100.00

To top of page

Top 25 of 101 countries of origin , sorted by number of files

N countries of origin times %


1 net 26,480 27.97
2 Germany 20,298 21.44
3 (unresolved) 15,354 16.22
4 com 7,508 7.93
5 Poland 2,313 2.44
6 Austria 2,263 2.39
7 Indonesia 1,882 1.99
8 edu 1,699 1.79
9 Switzerland 1,364 1.44
10 Italy 1,310 1.38
11 Netherlands 828 0.87
12 United Kingdom 760 0.80
13 India 734 0.78
14 Czech Republic 731 0.77
15 Greece 696 0.74
16 Belgium 648 0.68
17 Finland 603 0.64
18 Hungary 569 0.60
19 Mexico 534 0.56
20 Russian Federation 521 0.55
21 Canada 511 0.54
22 Romania 494 0.52
23 Brazil 492 0.52
24 Lithuania 467 0.49
25 Australia 381 0.40
Sum 94,657 100.00

To top of page

Top 25 of 132 pathes , sorted by number of files

N pathes times %
1 /common/ 32,607 34.45
2 /avr_gra/ 16,247 17.16
3 / 11,500 12.15
4 /avr_en/beginner/ 4,186 4.42
5 /avr_de/beginner/ 3,047 3.22
6 /avr_de/ 2,866 3.03
7 /avr_en/ 2,825 2.98
8 /avr_de/rechnen/ 1,847 1.95
9 /avr_en/calc/ 1,801 1.90
10 /avr_en/source/ 1,145 1.21
11 /avr_de/fcount/ 1,130 1.19
12 /avr_de/stepper/ 1,128 1.19
13 /avr_de/praesentation/ 1,076 1.14
14 /avr_de/quellen/ 1,007 1.06
15 /avr_en/keypad/ 907 0.96
16 /avr_de/keypad/ 820 0.87
17 /avr_en/stepper/ 799 0.84
/avr_de/rechteckgen/
18 777 0.82
bilder/
19 /gavrasm/ 713 0.75
20 /avr_de/zeitschleifen/ 683 0.72
21 /avr_en/signalgen/pics/ 677 0.72
22 /avr_de/interrupts/ 588 0.62
23 /privat/magloop/ 404 0.43
24 /akkuload/ 360 0.38
25 /privat/katomic/ 341 0.36
Sum 94,657 100.00

To top of page

Top 25 of 132 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 182,668 18.13
2 /avr_gra/ 129,506 12.86
3 /avr_de/intro/pdf/ 93,873 9.32
4 / 62,708 6.22
5 /avr_de/fcount/ 44,480 4.42
6 /avr_de/ 44,025 4.37
7 /avr_en/ 39,242 3.90
8 /avr_en/beginner/ 35,621 3.54
9 /avr_de/stepper/ 30,833 3.06
10 /avr_de/beginner/ 28,741 2.85
11 /avr_en/stepper/ 19,745 1.96
12 /avr_de/rechteckgen/bilder/ 19,339 1.92
13 /gavrasm/v21/ 19,139 1.90
14 /privat/magloop/ 19,029 1.89
15 /avr_en/signalgen/pics/ 17,896 1.78
16 /avr_en/calc/ 17,159 1.70
17 /avr_de/rechnen/ 16,757 1.66
18 /common/ 15,607 1.55
19 /avr_en/signalgen/ 15,179 1.51
20 /avr_de/intro/ppt/ 13,671 1.36
21 /avr_de/rechteckgen/ 12,818 1.27
/privat/stechlin/2005juni/
22 9,060 0.90
meilenweit/
23 /akkuload/ 8,807 0.87
24 /weblox_de/ 8,336 0.83
25 /weblox_en/ 7,142 0.71
Sum 1,007,422 100.00

To top of page

Top 25 of 1585 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 5,054 5.34
2 /avr_gra/RingLogo.jpg 2,575 2.72
3 /common/app.gif 2,123 2.24
/common/knowhow.
4 2,112 2.23
gif
5 /common/akkuload.gif 2,111 2.23
/common/download.
6 2,107 2.23
gif
7 /common/r2r.gif 2,095 2.21
8 /common/keyb.gif 2,094 2.21
9 /common/adc.gif 2,093 2.21
10 /avr_gra/stk_lcd.jpg 2,092 2.21
/common/gavrasmw.
11 2,092 2.21
gif
12 /common/calc.gif 2,092 2.21
13 /common/clock.gif 2,092 2.21
14 /common/example.gif 2,091 2.21
15 /common/beginner.gif 2,090 2.21
16 /common/gavrasm.gif 2,090 2.21
17 /common/hardware.gif 2,088 2.21
18 /index.html 1,536 1.62
19 /avr_en/index.html 1,223 1.29
20 /avr_de/index.html 1,219 1.29
21 /avr_2313.gif 1,209 1.28
22 /dg4fac.gif 1,204 1.27
23 /avr-asm-tutorial.gif 1,202 1.27
24 /avr_gra/2313.gif 1,133 1.20
25 /common/tn13.gif 1,080 1.14
Sum 94,657 100.00

To top of page

Top 25 of 1585 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 56,247 5.58
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 38,570 3.83
3 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 28,368 2.82
4 /avr_de/index.html 27,122 2.69
5 /avr_en/index.html 25,303 2.51
/avr_de/praesentation/Teil_5b_Beispiel01_02.
6 24,519 2.43
pdf
7 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 22,578 2.24
8 /avr_2313.gif 21,376 2.12
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 19,849 1.97
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 13,955 1.39
11 /dg4fac.gif 12,806 1.27
12 /avr_gra/pwm_simul.jpg 12,533 1.24
13 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 12,307 1.22
14 /avr_gra/r2r_hardware.jpg 9,994 0.99
15 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 9,962 0.99
16 /favicon.ico 9,934 0.99
17 /avr_en/signalgen/rectgen_m8.xls 9,891 0.98
18 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 9,683 0.96
19 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 8,904 0.88
20 /avr_de/fcount/dscf0004.jpg 8,536 0.85
21 /avr_de/intro/pdf/Teil1_Prozessor.pdf 8,379 0.83
22 /avr_en/signalgen/pics/rectgen_wiring.jpg 8,204 0.81
23 /index.html 8,028 0.80
24 /avr_gra/2313.gif 7,976 0.79
25 /avr_de/stepper/stepper_v1.gif 7,663 0.76
Sum 1,007,422 100.00

To top of page

Top 25 of 435 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,536 7.45
2 /avr_en/index.html 1,223 5.93
3 /avr_de/index.html 1,219 5.91
4 /avr_en/beginner/index.html 757 3.67
5 /avr_en/beginner/LEFT.html 735 3.57
6 /avr_en/beginner/RIGHT.html 727 3.53
7 /avr_de/beginner/index.html 470 2.28
8 /avr_de/beginner/links.html 464 2.25
9 /avr_de/beginner/rechts.html 429 2.08
/avr_en/beginner/HARDWARE.
10 270 1.31
html
11 /avr_en/beginner/REGISTER.html 244 1.18
12 /avr_en/beginner/JUMP.html 198 0.96
13 /avr_en/AVR_DAC.html 196 0.95
14 /avr_en/keypad/keyboard.html 187 0.91
15 /avr_en/beginner/PORTS.html 184 0.89
16 /avr_de/beginner/register.html 184 0.89
17 /avr_de/beginner/sprung.html 182 0.88
18 /avr_de/beginner/hardware.html 173 0.84
19 /avr_de/keypad/keyboard.html 172 0.83
20 /avr_de/praesentation/index.html 168 0.82
21 /avr_en/beginner/TOOLS.html 166 0.81
22 /avr_de/apps.html 163 0.79
23 /avr_de/beginner/ports.html 162 0.79
24 /avr_de/stepper/stepper.html 159 0.77
25 /avr_en/AVR_ADC500.html 150 0.73
Sum 20,612 100.00

To top of page

Top 25 of 435 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 27,122 11.55
2 /avr_en/index.html 25,303 10.78
3 /index.html 8,028 3.42
4 /avr_en/beginner/RIGHT.html 5,272 2.25
5 /avr_de/beginner/sprung.html 4,975 2.12
6 /avr_en/beginner/JUMP.html 4,813 2.05
7 /avr_de/dcf77uhr.html 4,320 1.84
8 /avr_en/keypad/keyboard.html 3,784 1.61
9 /gb_new.html 3,670 1.56
10 /avr_de/keypad/keyboard.html 3,611 1.54
11 /avr_en/beginner/CALC.html 3,432 1.46
12 /avr_en/beginner/LEFT.html 3,380 1.44
13 /avr_de/beginner/rechnen.html 3,132 1.33
14 /avr_de/beginner/rechts.html 3,032 1.29
15 /avr_en/beginner/REGISTER.html 3,016 1.28
16 /avr_en/AVR_DAC.html 2,896 1.23
17 /avr_en/beginner/PDETAIL.html 2,764 1.18
/avr_en/beginner/COMMANDS.
18 2,530 1.08
html
/avr_de/rechteckgen/rectgen_m8.
19 2,508 1.07
html
20 /avr_de/stepper/stepper.html 2,400 1.02
21 /avr_de/beginner/commands.html 2,333 0.99
22 /avr_en/AVR_ADC500.html 2,295 0.98
23 /avr_en/stepper/stepper.html 2,272 0.97
24 /sitemap_de.html 2,260 0.96
25 /avr_en/signalgen/rectgen_m8.html 2,247 0.96
Sum 234,728 100.00

To top of page

Top 25 of 449 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,575 18.64
2 /avr_gra/stk_lcd.jpg 2,092 15.14
3 /avr_gra/8515.jpg 575 4.16
4 /avr_gra/exp2313g.jpg 406 2.94
5 /avr_gra/avr_isp.jpg 405 2.93
6 /avr_gra/exp_2313.jpg 403 2.92
7 /avr_gra/r2r_wave.jpg 318 2.30
8 /avr_gra/r2r_sawtooth.jpg 300 2.17
9 /avr_gra/r2r_triangle.jpg 286 2.07
10 /avr_gra/r2r_hardware.jpg 286 2.07
11 /avr_gra/r2r_sawtoothupperbound.jpg 284 2.06
12 /avr_gra/r2r_upperbound.jpg 283 2.05
13 /avr_gra/r2r_sawtooth741.jpg 281 2.03
14 /avr_gra/AT90S8515.jpg 257 1.86
15 /avr_gra/pwm_simul.jpg 227 1.64
16 /avr_gra/apps.jpg 222 1.61
17 /avr_gra/adc8conn.jpg 221 1.60
18 /akkuload/dscf0030s.jpg 173 1.25
/avr_de/rechteckgen/bilder/rectgen_280.
19 165 1.19
jpg
20 /avr_de/stepper/stepper_sm.jpg 162 1.17
21 /avr_gra/stk200lcd.jpg 153 1.11
22 /avr_en/signalgen/pics/rectgen_280.jpg 152 1.10
23 /avr_de/stepper/supply.jpg 151 1.09
24 /avr_de/praesentation/zuendtester.jpg 150 1.09
25 /avr_de/stepper/kp4m4-001.jpg 149 1.08
Sum 13,816 100.00

To top of page

Top 25 of 395 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 2,123 4.28
/common/knowhow.
2 2,112 4.25
gif
3 /common/akkuload.gif 2,111 4.25
/common/download.
4 2,107 4.24
gif
5 /common/r2r.gif 2,095 4.22
6 /common/keyb.gif 2,094 4.22
7 /common/adc.gif 2,093 4.22
/common/gavrasmw.
8 2,092 4.21
gif
9 /common/calc.gif 2,092 4.21
10 /common/clock.gif 2,092 4.21
11 /common/example.gif 2,091 4.21
12 /common/beginner.gif 2,090 4.21
13 /common/gavrasm.gif 2,090 4.21
14 /common/hardware.gif 2,088 4.21
15 /avr_2313.gif 1,209 2.44
16 /dg4fac.gif 1,204 2.42
17 /avr-asm-tutorial.gif 1,202 2.42
18 /avr_gra/2313.gif 1,133 2.28
19 /common/tn13.gif 1,080 2.18
20 /common/ints.gif 1,079 2.17
21 /common/delay.gif 1,078 2.17
22 /avr_gra/exp2313.gif 413 0.83
23 /avr_gra/isp10pin.gif 411 0.83
24 /avr_gra/isp6pin.gif 407 0.82
25 /avr_gra/avr_isp.gif 401 0.81
Sum 49,650 100.00

To top of page

Top 25 of 182 entry pages , sorted by number of files

N entry pages times %


1 /index.html 752 16.52
2 /avr_en/index.html 471 10.35
3 /avr_de/index.html 390 8.57
4 /avr_en/beginner/index.html 253 5.56
5 /avr_en/AVR_DAC.html 126 2.77
6 /avr_de/beginner/index.html 123 2.70
7 /avr_de/stepper/stepper.html 92 2.02
8 /avr_en/beginner/HARDWARE.html 82 1.80
9 /avr_de/keypad/keyboard.html 71 1.56
10 /avr_en/keypad/keyboard.html 68 1.49
11 /avr_en/signalgen/rectgen_m8.html 66 1.45
12 /avr_en/AVR_ADC500.html 65 1.43
13 /avr_de/avr_dac.html 62 1.36
/avr_de/rechteckgen/rectgen_m8.
14 62 1.36
html
15 /avr_de/fcount/fcount_m8.html 61 1.34
16 /avr_de/intro/index.html 53 1.16
17 /avr_en/stepper/stepper.html 44 0.97
18 /avr_en/beginner/SRAM.html 41 0.90
19 /avr_de/rechnen/konversion.html 41 0.90
20 /avr_de/beginner/hardware.html 40 0.88
21 /avr_en/beginner/REGISTER.html 40 0.88
22 /avr_de/beginner/sprung.html 39 0.86
23 /avr_de/avr_adc500.html 38 0.83
24 /gb_new.html 36 0.79
/avr_en/beginner/COMMANDS.
25 35 0.77
html
Sum 4,551 100.00

To top of page

Top 25 of 212 cheat pages , sorted by number of files

N cheat pages times %


1 886 14.82
2 /index.html 493 8.25
3 /avr_en/index.html 367 6.14
4 /avr_de/index.html 317 5.30
5 /avr_en/beginner/RIGHT.html 147 2.46
6 /avr_en/AVR_DAC.html 134 2.24
7 /avr_en/beginner/HARDWARE.html 115 1.92
8 /avr_de/keypad/keyboard.html 94 1.57
9 /avr_de/stepper/stepper.html 93 1.56
10 /avr_en/keypad/keyboard.html 87 1.46
11 /avr_en/beginner/REGISTER.html 85 1.42
12 /avr_en/AVR_ADC500.html 79 1.32
13 /avr_de/beginner/rechts.html 77 1.29
14 /avr_en/beginner/SRAM.html 64 1.07
15 /avr_en/beginner/JUMP.html 62 1.04
16 /avr_de/avr_dac.html 61 1.02
17 /akkuload/de/index.html 58 0.97
/avr_de/rechteckgen/rectgen_m8.
18 58 0.97
html
19 /avr_en/signalgen/rectgen_m8.html 58 0.97
20 /avr_de/beginner/hardware.html 55 0.92
21 /avr_de/beginner/sprung.html 54 0.90
22 /avr_de/beginner/rechnen.html 54 0.90
23 /avr_de/praesentation/index.html 53 0.89
24 /avr_de/fcount/fcount_m8.html 49 0.82
25 /avr_de/intro/index.html 47 0.79
Sum 5,978 100.00

To top of page

Top 25 of 175 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,669 16.55
2 /avr_en/beginner/index.html 1,283 12.72
3 /avr_de/beginner/index.html 809 8.02
4 / 640 6.35
5 /avr_en/index.html 617 6.12
6 /avr_en/beginner/RIGHT.html 574 5.69
7 /avr_en/ 551 5.46
8 /avr_de/beginner/rechts.html 434 4.30
9 /avr_en/beginner/LEFT.html 413 4.09
10 /avr_de/beginner/links.html 291 2.89
11 /sitemap_de.html 221 2.19
12 /sitemap_en.html 187 1.85
13 /avr_de/apps.html 174 1.73
14 /avr_de/interrupts/index.html 157 1.56
15 /index.html 135 1.34
16 /avr_de/zeitschleifen/index.html 126 1.25
17 /avr_de/avr_tut.html 119 1.18
18 /avr_en/calc/index.html 115 1.14
19 /avr_en/AVR_TUT.html 110 1.09
20 /avr_en/APPS.html 72 0.71
21 /avr_de/rechnen/index.html 69 0.68
22 /avr_de/ 58 0.58
23 /avr_de/beginner/commands.html 58 0.58
/avr_en/signalgen/rectgen_m8.
24 54 0.54
html
25 /avr_en/beginner/PORTS.html 50 0.50
Sum 10,086 100.00

To top of page

Top 25 of 378 external referrers , sorted by number of files

N external referrers times %


1 - 5,800 85.42
2 http://www.mikrocontroller.net/articles/AVR 54 0.80
3 http://www.webring.com/hub?ring=avr 35 0.52
http://www.avrfreaks.net/index.php?
4 name=PNphpBB2&file=viewtopic&t=7067 20 0.29
3
5 http://mathcs.slu.edu/~fritts/csci305_306/links.html 18 0.27
http://electrons.psychogenic.com/modules/arms/art/3/
6 AVRGCCProgrammingG 17 0.25
uide.php
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 17 0.25
8 http://www.dg4fac.de/linksunten.html 17 0.25
9 http://de.wikipedia.org/wiki/R2R-Netzwerk 16 0.24
10 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 16 0.24
11 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 15 0.22
12 http://avr-asm.tripod.com/ 15 0.22
13 http://www.attiny.com/avrlinks.htm 14 0.21
14 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 14 0.21
15 http://www.rowalt.de/mc/avr/linksd.htm 13 0.19
16 http://www.educypedia.be/electronics/avr.htm 13 0.19
17 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 12 0.18
18 http://www.dg4fac.de/rechtsunten.html 12 0.18
19 http://circuit.lt/?section=sch&page=avr.isp.lpt 11 0.16
20 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 10 0.15
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
21 10 0.15
ESC_by1_bz0_bs0.html
22 http://www.mikrocontroller.net/articles/Linksammlung 10 0.15
23 http://www.heni-online.de/java/atomicplay_js.php 9 0.13
24 http://www.eg3.com/WebID/embedded/avr/blank/tutorial/a-z.htm 9 0.13
25 http://it.wikipedia.org/wiki/Atmel_AVR 8 0.12
Sum 6,790 100.00

To top of page

Top 25 of 124 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,473 41.57
2 http://www.google.com 763 21.54
3 http://www.google.at 112 3.16
4 http://www.google.co.uk 104 2.94
5 http://www.google.co.in 80 2.26
6 http://www.google.ch 54 1.52
7 http://www.google.pl 49 1.38
8 http://www.google.ca 45 1.27
9 http://www.google.gr 44 1.24
10 http://www.google.nl 35 0.99
11 http://www.google.cz 34 0.96
12 http://www.google.co.id 32 0.90
http://www.google.com.
13 28 0.79
au
14 http://www.google.hr 27 0.76
15 http://search.live.com 24 0.68
16 http://www.google.se 23 0.65
17 http://www.google.it 23 0.65
18 http://www.google.be 22 0.62
19 http://www.google.ro 21 0.59
20 http://www.google.fi 20 0.56
21 http://search.yahoo.com 20 0.56
http://de.search.yahoo.
22 18 0.51
com
23 http://www.google.ru 18 0.51
24 http://www.google.hu 18 0.51
25 http://www.google.es 17 0.48
Sum 3,543 100.00

To top of page

Top 25 of 2378 search strings , sorted by number of files

N search strings times %


1 avr tutorial 93 2.62
2 avr assembler 58 1.64
3 avr programming 49 1.38
4 avr 38 1.07
5 attiny13 33 0.93
6 assembler 31 0.87
7 avr assembly 27 0.76
8 assembler tutorial 24 0.68
9 avr asm 23 0.65
10 atmega8 22 0.62
11 ATtiny13 18 0.51
12 AVR tutorial 14 0.40
assembler
13 13 0.37
commands
14 AVR programming 10 0.28
15 AVR 10 0.28
16 stk500 lcd 10 0.28
avr assembler
17 9 0.25
tutorial
18 r2r network 9 0.25
19 avr tutorials 9 0.25
20 avr division 9 0.25
21 gavrasm 9 0.25
22 avr programing 8 0.23
23 asm tutorial 8 0.23
24 AVR Assembler 8 0.23
25 tutorial avr 8 0.23
Sum 3,543 100.00

To top of page

Top 8 of 8 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 84,781 89.57
2 304 Not changed 9,032 9.54
3 206 Partial information 412 0.44
4 404 File not found 208 0.22
5 301 Permanently moved 191 0.20

http://www.avr-asm-tutorial.net/weblox_en/2008w49.html (1 of 2)1/20/2009 8:09:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

6 403 Forbidden 17 0.02


7 300 Multiple choices 14 0.01
8 400 Error in request 2 0.00
Sum 94,657 100.00

To top of page

Top 25 of 91 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 53 25.48
2 /beginner_de.pdf 14 6.73
3 /_vti_inf.html 14 6.73
/_vti_bin/owssvr.dll?
4 7 3.37
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
5 7 3.37
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
6 /sitemap.xml 5 2.40
7 /avr_en/keypad/index.htm 3 1.44
8 /avr_en/stepper/index.htm 3 1.44
9 /avr_en/eggtimer/index.htm 3 1.44
10 /avr_en/signalgen/index.htm 3 1.44
11 /avr_de/praesentation/favicon.ico 3 1.44
12 /avr_de/praesentation/favicon.gif 3 1.44
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
13 20AVR-Assemble 2 0.96
r-Dateien/links.htm
/avr_en/source/R2R-network-2520calculation-2520tool,-2520(C)2004-2520i
14 2 0.96
nfo-40avr-asm-tutorial.net
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
15 20la 2 0.96
nguage_files/LEFT.htm
/_vti_bin/owssvr.dll?
16 2 0.96
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
17 2 0.96
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/avr_en/keypad/keyboard.html//include/global.php?pfad=http://perazimme
18 2 0.96
dia.com/helpdesk/idscan9?
19 //include/global.php?pfad=http://perazimmedia.com/helpdesk/idscan9? 2 0.96
/avr_en/keypad//include/global.php?pfad=http://perazimmedia.com/helpde
20 2 0.96
sk/idscan9?
/avr_en/beginner/HARDWARE.html//include/global.php?pfad=http://perazim
21 2 0.96
media.com/helpdesk/idscan9?
/avr_en/beginner//include/global.php?pfad=http://perazimmedia.com/help
22 2 0.96
desk/idscan9?
23 /HTTP_OPENPGP_DISCOVERY 2 0.96
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
24 20AVR-Assemble 1 0.48
r-Dateien/rechts.htm
25 /avr_en/source/Input%20operating%20voltage%20...%20 1 0.48
Sum 208 100.00

To top of page

Top 25 of 115 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 50,364 53.21
2 Mozilla/4.0 36,337 38.39
3 Opera/9.62 2,086 2.20
4 Opera/9.61 595 0.63
5 Yanga 588 0.62
6 Opera/9.60 456 0.48
7 Opera/9.27 421 0.44
8 Opera/9.52 396 0.42
9 Yandex/1.01.001 335 0.35
10 msnbot-media/1.1 335 0.35
11 Mozilla/4.5 302 0.32
12 Opera/9.51 269 0.28
Googlebot-
13 260 0.27
Image/1.0
14 Opera/9.50 250 0.26
15 msnbot/1.1 229 0.24
16 Safari/5525.27.1 130 0.14
17 Opera/9.25 90 0.10
18 - 80 0.08
19 ia_archiver 75 0.08
20 Mozilla/3.01 74 0.08
21 Opera/9.26 74 0.08
22 msnbot-media/1.0 69 0.07
23 Speedy 68 0.07
24 Opera/8.50 64 0.07
25 CazoodleBot/0.0.2 50 0.05
Sum 94,657 100.00

To top of page

Top 25 of 265 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 27,736 29.30
2 MSIE 7.0 20,151 21.29
3 MSIE 6.0 12,628 13.34
4 Firefox/2.0.0.18 3,515 3.71
5 Gecko 2,804 2.96
6 Opera/9.62 2,085 2.20
7 unknown 1,784 1.88
8 Firefox/3.0.3 1,757 1.86
9 Firefox/3.0.4 1,747 1.85
10 Firefox/3.0.1 1,625 1.72
11 MSIE 5.0 1,455 1.54
12 Slurp 1,447 1.53
13 Googlebot/2.1 658 0.70
14 Firefox/3.0 634 0.67
15 Opera/9.61 595 0.63
16 Opera/9.60 456 0.48
17 Firefox/2.0.0.14 436 0.46
18 Opera/9.27 421 0.44
19 Firefox/2.0.0.17 416 0.44
20 Opera/9.52 396 0.42
Gecko/2008092816
21 391 0.41
Iceweasel/3.0.3
22 Firefox/2.0 338 0.36
23 Yandex/1.01.001 335 0.35
24 msnbot-media/1.1 335 0.35
25 Slurp/3.0 324 0.34
Sum 94,657 100.00

To top of page

Top 25 of 40 operating systems , sorted by number of files

N operating systems times %


1 Windows 39,056 41.26
2 Windows NT 5.1 32,569 34.41
3 unknown 6,231 6.58
4 Linux i686 4,653 4.92
5 Windows NT 6.0 4,318 4.56
6 Windows NT 4.0 1,378 1.46
7 Windows NT 5.0 1,266 1.34
8 Linux x86_64 913 0.96
9 Windows 98 715 0.76
10 Mac OS X 10_5_5 675 0.71
11 Mac OS X 10.5 549 0.58
12 Linux 454 0.48
13 Windows NT 5.2 352 0.37
14 Win16 337 0.36
15 Mac OS X 10.4 195 0.21
16 Windows XP 5.1 159 0.17
17 Linux 2.6.24.4 135 0.14
18 Mac OS X 107 0.11
19 Mac OS X 10_4_11 104 0.11
20 Linux i686 97 0.10
21 Windows 6.0 95 0.10
22 Windows 32-bit 63 0.07
23 Mac OS X 10_5_4 38 0.04
24 Windows NT 33 0.03
FreeBSD/i386
25 29 0.03
Firefox/2.0.0.12
Sum 94,657 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,810 2.97
2 01 2,224 2.35
3 02 1,855 1.96
4 03 1,905 2.01
5 04 1,591 1.68
6 05 1,473 1.56
7 06 1,510 1.60
8 07 2,114 2.23
9 08 2,808 2.97
10 09 3,482 3.68
11 10 4,041 4.27
12 11 4,311 4.55
13 12 5,457 5.77
14 13 4,562 4.82
15 14 6,033 6.37
16 15 6,270 6.62
17 16 5,968 6.30
18 17 5,599 5.92
19 18 5,073 5.36
20 19 5,603 5.92
21 20 5,518 5.83
22 21 5,394 5.70
23 22 4,931 5.21
24 23 4,125 4.36
Sum 94,657 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w49.html (2 of 2)1/20/2009 8:09:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w48

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 48

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5602 IPs and host names , sorted by number of files

N IPs and host names times %


1 200.75.53.86=corporat200-075053086.sta.etb.net.co 738 0.81
2 194.254.62.54=www.lyc-edouardbranly.ac-poitiers.fr 643 0.70
3 67.195.37.109=llf320031.crawl.yahoo.net 639 0.70
4 91.16.156.58=p5B109C3A.dip0.t-ipconnect.de 630 0.69
5 79.129.247.65=athedsl-4458321.home.otenet.gr 616 0.67
6 84.77.129.90=(not found) 559 0.61
7 66.249.72.79=crawl-66-249-72-79.googlebot.com 509 0.56
8 91.205.124.9=(not found) 496 0.54
69.145.167.81=host-69-145-167-81.grf-mt.client.bresnan.
9 345 0.38
net
10 92.105.57.123=123-57.105-92.cust.bluewin.ch 338 0.37
11 216.158.1.200=(not found) 284 0.31
12 62.154.211.219=pwm.pwm.com 266 0.29
13 202.150.129.204=server.cinovasi.com 262 0.29
14 213.29.4.68=(not found) 239 0.26
15 82.113.106.16=16.106.113.82.net.de.o2.com 217 0.24
16 213.60.109.204=(not found) 200 0.22
17 78.62.69.167=78-62-69-167.static.zebra.lt 197 0.22
18 208.111.154.16=crawl2.nat.svl.searchme.com 195 0.21
19 64.128.171.4=64-128-171-4.static.twtelecom.net 191 0.21
20 62.159.20.190=(not found) 175 0.19
21 91.67.186.89=91-67-186-89-dynip.superkabel.de 170 0.19
22 71.16.168.194=mail.regencyelectric.com 169 0.18
23 89.14.212.30=manz-590ed41e.pool.einsundeins.de 164 0.18
24 24.230.219.244=24-230-219-244.dr.cgocable.ca 163 0.18
25 38.108.180.146=h-180-146.scoutjet.com 153 0.17
Sum 91,390 100.00

To top of page

Top 25 of 5602 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 194.254.62.54=www.lyc-edouardbranly.ac-poitiers.fr 17,034 1.80
2 91.16.156.58=p5B109C3A.dip0.t-ipconnect.de 16,285 1.72
3 79.129.247.65=athedsl-4458321.home.otenet.gr 15,200 1.60
4 91.205.124.9=(not found) 9,842 1.04
5 67.195.37.109=llf320031.crawl.yahoo.net 9,719 1.03
6 84.77.129.90=(not found) 7,970 0.84
7 217.235.194.135=pD9EBC287.dip.t-dialin.net 7,727 0.82
8 212.68.67.10=(not found) 6,544 0.69
9 200.75.53.86=corporat200-075053086.sta.etb.net.co 5,521 0.58
10 212.175.206.67=(not found) 5,027 0.53
11 217.91.17.4=pd95b1104.dip0.t-ipconnect.de 4,789 0.51
12 92.104.118.168=168-118.104-92.cust.bluewin.ch 4,643 0.49
13 87.170.215.1=p57AAD701.dip.t-dialin.net 4,623 0.49
14 134.130.243.76=3-076.vpn.RWTH-Aachen.DE 4,573 0.48
15 91.66.27.228=91-66-27-228-dynip.superkabel.de 4,549 0.48
16 91.33.124.89=p5B217C59.dip.t-dialin.net 4,465 0.47
17 80.109.239.142=chello080109239142.wrn.surfer.at 4,352 0.46
18 66.249.72.79=crawl-66-249-72-79.googlebot.com 4,185 0.44
19 143.164.102.13=webprx1.audi.de 4,038 0.43
20 64.128.171.4=64-128-171-4.static.twtelecom.net 4,028 0.43
21 62.178.3.56=chello062178003056.2.11.vie.surfer.at 3,913 0.41
22 195.145.184.178=(not found) 3,894 0.41
23 91.0.224.53=p5B00E035.dip.t-dialin.net 3,771 0.40
84.60.246.137=dslb-084-060-246-137.pools.arcor-ip.
24 3,763 0.40
net
25 80.187.96.194=tmo-096-194.customers.d1-online.com 3,762 0.40
Sum 947,417 100.00

To top of page

Top 25 of 940 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 128 3.60
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 109 3.07
3 208.111.154.16=crawl2.nat.svl.searchme.com 61 1.72
4 66.235.124.3=crawler5003.ask.com 47 1.32
5 208.111.154.15=crawl1.nat.svl.searchme.com 46 1.30
6 81.52.143.16=natcrawlbloc03.net.m1.fti.net 34 0.96
7 81.52.143.26=natcrawlbloc05.net.m1.fti.net 33 0.93
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 33 0.93
9 88.131.106.16=(not found) 31 0.87
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 31 0.87
11 67.195.37.115=llf320028.crawl.yahoo.net 21 0.59
12 91.67.186.89=91-67-186-89-dynip.superkabel.de 18 0.51
13 193.252.149.16=natcrawlbloc04.net.s1.fti.net 18 0.51
14 193.47.80.44=crawl8.exabot.com 18 0.51
15 216.158.1.200=(not found) 17 0.48
16 194.39.218.10=http-v.fe.bosch.de 17 0.48
17 88.118.153.89=(not found) 16 0.45
18 65.55.212.136=(not found) 14 0.39
67.202.58.81=ec2-67-202-58-81.compute-1.amazonaws.
19 14 0.39
com
20 65.55.209.151=msnbot-65-55-209-151.search.msn.com 14 0.39
21 65.55.209.168=msnbot-65-55-209-168.search.msn.com 14 0.39
22 208.111.154.27=v27.nat.svl.searchme.com 14 0.39
23 65.55.209.153=msnbot-65-55-209-153.search.msn.com 13 0.37
24 38.108.180.146=h-180-146.scoutjet.com 12 0.34
25 221.216.20.242=(not found) 12 0.34
Sum 3,551 100.00

To top of page

Top 25 of 95 countries of origin , sorted by number of files

N countries of origin times %


1 net 23,899 26.15
2 Germany 20,349 22.27
3 (unresolved) 17,246 18.87
4 com 6,885 7.53
5 Poland 1,841 2.01
6 Austria 1,824 2.00
7 Switzerland 1,549 1.69
8 Greece 1,092 1.19
9 Colombia 873 0.96
10 Italy 823 0.90
11 Czech Republic 808 0.88
12 Netherlands 804 0.88
13 India 724 0.79
14 France 716 0.78
15 Belgium 676 0.74
16 Finland 647 0.71
17 Canada 634 0.69
18 Indonesia 626 0.68
19 Lithuania 592 0.65
20 Australia 566 0.62
21 Hungary 553 0.61
22 Brazil 552 0.60
23 Romania 551 0.60
24 Spain 465 0.51
25 Russian Federation 431 0.47
Sum 91,390 100.00

To top of page

Top 25 of 118 pathes , sorted by number of files

N pathes times %
1 /common/ 32,356 35.40
2 /avr_gra/ 16,214 17.74
3 / 10,581 11.58
4 /avr_en/beginner/ 4,120 4.51
5 /avr_de/beginner/ 3,102 3.39
6 /avr_en/ 2,817 3.08
7 /avr_de/ 2,782 3.04
8 /avr_en/calc/ 2,001 2.19
9 /avr_de/stepper/ 1,369 1.50
10 /avr_de/fcount/ 1,255 1.37
11 /avr_de/rechnen/ 1,229 1.34
12 /avr_en/source/ 1,193 1.31
13 /avr_de/praesentation/ 1,093 1.20
14 /avr_de/quellen/ 905 0.99
15 /avr_en/keypad/ 845 0.92
16 /avr_en/stepper/ 726 0.79
17 /avr_de/keypad/ 706 0.77
18 /gavrasm/ 698 0.76
/avr_de/rechteckgen/
19 667 0.73
bilder/
20 /avr_en/signalgen/pics/ 611 0.67
21 /avr_de/zeitschleifen/ 578 0.63
22 /privat/magloop/ 518 0.57
23 /avr_de/interrupts/ 518 0.57
24 /akkuload/ 342 0.37
25 /avr_en/signalgen/ 298 0.33
Sum 91,390 100.00

To top of page

Top 25 of 118 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 190,451 20.10
2 /avr_gra/ 127,619 13.47
3 /avr_de/intro/pdf/ 60,871 6.42
4 / 58,483 6.17
5 /avr_de/fcount/ 50,630 5.34
6 /avr_de/ 44,806 4.73
7 /avr_en/ 38,350 4.05
8 /avr_de/stepper/ 36,209 3.82
9 /avr_en/beginner/ 35,022 3.70
10 /avr_de/beginner/ 30,438 3.21
11 /privat/magloop/ 25,789 2.72
12 /gavrasm/v21/ 21,664 2.29
13 /avr_en/calc/ 19,288 2.04
14 /avr_en/stepper/ 18,855 1.99
/avr_de/rechteckgen/
15 17,964 1.90
bilder/
16 /avr_en/signalgen/pics/ 16,521 1.74
17 /common/ 15,797 1.67
18 /avr_en/signalgen/ 13,209 1.39
19 /avr_de/rechnen/ 11,603 1.22
20 /avr_de/rechteckgen/ 8,727 0.92
21 /avr_de/intro/ppt/ 8,545 0.90
22 /akkuload/ 8,492 0.90
23 /avr_en/keypad/ 6,250 0.66
24 /avr_de/interrupts/ 5,798 0.61
25 /gavrasm/gavrasmw/ 5,753 0.61
Sum 947,417 100.00

To top of page

Top 25 of 1228 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,857 5.31
2 /avr_gra/RingLogo.jpg 2,477 2.71
3 /avr_gra/stk_lcd.jpg 2,092 2.29
4 /common/akkuload.gif 2,091 2.29
5 /common/app.gif 2,088 2.28
/common/knowhow.
6 2,084 2.28
gif
/common/download.
7 2,084 2.28
gif
8 /common/clock.gif 2,079 2.27
9 /common/gavrasm.gif 2,078 2.27
10 /common/example.gif 2,076 2.27
11 /common/beginner.gif 2,074 2.27
12 /common/keyb.gif 2,073 2.27
/common/gavrasmw.
13 2,069 2.26
gif
14 /common/adc.gif 2,067 2.26
15 /common/calc.gif 2,067 2.26
16 /common/r2r.gif 2,066 2.26
17 /common/hardware.gif 2,062 2.26
18 /index.html 1,427 1.56
19 /avr_de/index.html 1,228 1.34
20 /avr_en/index.html 1,190 1.30
21 /common/delay.gif 1,104 1.21
22 /common/ints.gif 1,098 1.20
23 /common/tn13.gif 1,096 1.20
24 /avr_gra/2313.gif 1,075 1.18
25 /avr_2313.gif 1,058 1.16
Sum 91,390 100.00

To top of page

Top 25 of 1228 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 63,841 6.74
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 40,331 4.26
3 /avr_de/index.html 27,850 2.94
4 /avr_en/index.html 24,197 2.55
/avr_de/praesentation/Teil_5b_Beispiel01_02.
5 23,619 2.49
pdf
6 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 19,107 2.02
7 /avr_2313.gif 19,028 2.01
8 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 18,815 1.99
9 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 18,713 1.98
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 14,250 1.50
11 /dg4fac.gif 11,417 1.21
12 /avr_gra/r2r_hardware.jpg 10,435 1.10
13 /avr_gra/pwm_simul.jpg 9,988 1.05
14 /avr_de/fcount/dscf0004.jpg 9,926 1.05
15 /avr_de/intro/pdf/Teil1_Prozessor.pdf 9,516 1.00
16 /favicon.ico 9,460 1.00
17 /avr_de/stepper/stepper_v1.gif 8,991 0.95
18 /avr_de/fcount/dscf0005.jpg 8,724 0.92
19 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 8,316 0.88
20 /avr_gra/exp2313.gif 8,118 0.86
21 /avr_de/fcount/dscf0001.jpg 8,116 0.86
22 /avr_gra/2313.gif 7,664 0.81
23 /index.html 7,621 0.80
24 /avr_en/signalgen/pics/rectgen_wiring.jpg 7,510 0.79
25 /avr_gra/stk_lcd.jpg 7,368 0.78
Sum 947,417 100.00

To top of page

Top 25 of 300 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,427 7.21
2 /avr_de/index.html 1,228 6.20
3 /avr_en/index.html 1,190 6.01
4 /avr_en/beginner/index.html 705 3.56
5 /avr_en/beginner/RIGHT.html 676 3.42
6 /avr_en/beginner/LEFT.html 667 3.37
7 /avr_de/beginner/index.html 460 2.32
8 /avr_de/beginner/rechts.html 457 2.31
9 /avr_de/beginner/links.html 448 2.26
/avr_en/beginner/HARDWARE.
10 299 1.51
html
11 /avr_en/beginner/REGISTER.html 259 1.31
12 /avr_en/AVR_DAC.html 201 1.02
13 /avr_de/beginner/hardware.html 201 1.02
14 /avr_en/beginner/JUMP.html 193 0.98
15 /avr_de/beginner/register.html 191 0.97
16 /avr_de/stepper/stepper.html 187 0.94
17 /avr_en/beginner/PORTS.html 181 0.91
18 /avr_en/beginner/TOOLS.html 174 0.88
19 /avr_en/keypad/keyboard.html 174 0.88
20 /avr_de/praesentation/index.html 160 0.81
21 /avr_de/beginner/ports.html 155 0.78
22 /avr_de/beginner/sprung.html 154 0.78
23 /avr_de/apps.html 154 0.78
24 /avr_en/beginner/SRAM.html 152 0.77
25 /avr_de/beginner/werkzeuge.html 152 0.77
Sum 19,792 100.00

To top of page

Top 25 of 300 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 27,850 12.76
2 /avr_en/index.html 24,197 11.08
3 /index.html 7,621 3.49
4 /avr_de/dcf77uhr.html 4,860 2.23
5 /avr_en/beginner/RIGHT.html 4,808 2.20
6 /avr_en/beginner/JUMP.html 4,446 2.04
7 /avr_de/beginner/sprung.html 4,247 1.95
8 /gb_new.html 3,978 1.82
9 /avr_en/beginner/CALC.html 3,614 1.66
10 /avr_de/beginner/rechnen.html 3,610 1.65
11 /avr_en/keypad/keyboard.html 3,586 1.64
12 /avr_de/beginner/rechts.html 3,240 1.48
13 /avr_en/beginner/REGISTER.html 3,165 1.45
14 /avr_en/beginner/LEFT.html 3,060 1.40
15 /avr_de/keypad/keyboard.html 3,036 1.39
16 /avr_de/beginner/pdetail.html 2,987 1.37
17 /avr_en/AVR_DAC.html 2,960 1.36
/avr_en/beginner/COMMANDS.
18 2,904 1.33
html
19 /avr_de/stepper/stepper.html 2,784 1.28
20 /avr_de/avr_dac.html 2,394 1.10
21 /avr_en/AVR_ADC500.html 2,329 1.07
22 /avr_de/beginner/commands.html 2,310 1.06
/avr_de/rechteckgen/rectgen_m8.
23 2,310 1.06
html
24 /sitemap_de.html 2,260 1.04
25 /avr_en/beginner/PDETAIL.html 2,156 0.99
Sum 218,326 100.00

To top of page

Top 25 of 282 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,477 18.71
2 /avr_gra/stk_lcd.jpg 2,092 15.80
3 /avr_gra/8515.jpg 469 3.54
4 /avr_gra/avr_isp.jpg 455 3.44
5 /avr_gra/exp2313g.jpg 455 3.44
6 /avr_gra/exp_2313.jpg 450 3.40
7 /avr_gra/r2r_sawtooth.jpg 347 2.62
8 /avr_gra/r2r_wave.jpg 316 2.39
9 /avr_gra/r2r_triangle.jpg 292 2.21
10 /avr_gra/r2r_hardware.jpg 292 2.21
11 /avr_gra/r2r_sawtoothupperbound.jpg 290 2.19
12 /avr_gra/r2r_upperbound.jpg 290 2.19
13 /avr_gra/r2r_sawtooth741.jpg 289 2.18
14 /avr_gra/AT90S8515.jpg 254 1.92
15 /avr_gra/apps.jpg 200 1.51
16 /avr_de/stepper/stepper_sm.jpg 190 1.43
17 /avr_de/stepper/kp4m4-001.jpg 184 1.39
18 /avr_gra/adc8conn.jpg 181 1.37
19 /avr_gra/pwm_simul.jpg 180 1.36
20 /avr_de/stepper/driver.jpg 180 1.36
21 /avr_de/stepper/supply.jpg 178 1.34
22 /akkuload/dscf0030s.jpg 161 1.22
23 /avr_en/signalgen/pics/rectgen_280.jpg 143 1.08
24 /avr_de/praesentation/zuendtester.jpg 139 1.05
/avr_de/rechteckgen/bilder/rectgen_280.
25 137 1.03
jpg
Sum 13,242 100.00

To top of page

Top 25 of 336 GIF-files , sorted by number of files

N GIF-files times %
1 /common/akkuload.gif 2,091 4.32
2 /common/app.gif 2,088 4.31
/common/knowhow.
3 2,084 4.30
gif
/common/download.
4 2,084 4.30
gif
5 /common/clock.gif 2,079 4.29
6 /common/gavrasm.gif 2,078 4.29
7 /common/example.gif 2,076 4.29
8 /common/beginner.gif 2,074 4.28
9 /common/keyb.gif 2,073 4.28
/common/gavrasmw.
10 2,069 4.27
gif
11 /common/adc.gif 2,067 4.27
12 /common/calc.gif 2,067 4.27
13 /common/r2r.gif 2,066 4.27
14 /common/hardware.gif 2,062 4.26
15 /common/delay.gif 1,104 2.28
16 /common/ints.gif 1,098 2.27
17 /common/tn13.gif 1,096 2.26
18 /avr_gra/2313.gif 1,075 2.22
19 /avr_2313.gif 1,058 2.19
20 /dg4fac.gif 1,052 2.17
21 /avr-asm-tutorial.gif 1,046 2.16
22 /avr_gra/screenshot.gif 475 0.98
23 /avr_gra/exp2313.gif 475 0.98
24 /avr_gra/avr_isp.gif 455 0.94
25 /avr_gra/isp10pin.gif 453 0.94
Sum 48,420 100.00

To top of page

Top 25 of 166 entry pages , sorted by number of files

N entry pages times %


1 /index.html 649 15.14
2 /avr_en/index.html 468 10.92
3 /avr_de/index.html 454 10.59
4 /avr_en/beginner/index.html 230 5.37
5 /avr_en/AVR_DAC.html 111 2.59
6 /avr_de/beginner/index.html 111 2.59
7 /avr_de/stepper/stepper.html 101 2.36
8 /avr_en/beginner/HARDWARE.html 79 1.84
9 /avr_de/avr_dac.html 79 1.84
10 /avr_en/keypad/keyboard.html 65 1.52
11 /avr_de/keypad/keyboard.html 64 1.49
12 /avr_de/fcount/fcount_m8.html 61 1.42
13 /avr_en/AVR_ADC500.html 61 1.42
/avr_de/rechteckgen/rectgen_m8.
14 61 1.42
html
15 /avr_en/signalgen/rectgen_m8.html 50 1.17
16 /avr_de/intro/index.html 49 1.14
17 /avr_en/stepper/stepper.html 49 1.14
18 /avr_en/beginner/SRAM.html 44 1.03
19 /avr_en/beginner/REGISTER.html 43 1.00
20 /privat/magloop/index.html 42 0.98
21 /gb_new.html 37 0.86
22 /avr_de/rechnen/konversion.html 37 0.86
23 /avr_de/avr_adc500.html 34 0.79
/avr_en/beginner/COMMANDS.
24 32 0.75
html
25 /avr_de/rechnen/multiplikation.html 31 0.72
Sum 4,287 100.00

To top of page

Top 25 of 200 cheat pages , sorted by number of files

N cheat pages times %


1 774 13.82
2 /index.html 381 6.80
3 /avr_en/index.html 336 6.00
4 /avr_de/index.html 334 5.96
5 /avr_en/beginner/RIGHT.html 169 3.02
6 /avr_en/AVR_DAC.html 122 2.18
7 /avr_en/beginner/HARDWARE.html 105 1.87
8 /avr_de/stepper/stepper.html 100 1.79
9 /avr_en/keypad/keyboard.html 92 1.64
10 /avr_de/avr_dac.html 88 1.57
11 /avr_en/beginner/REGISTER.html 87 1.55
12 /avr_de/keypad/keyboard.html 79 1.41
13 /avr_de/beginner/rechts.html 63 1.12
14 /avr_en/AVR_ADC500.html 62 1.11
15 /avr_en/beginner/JUMP.html 62 1.11
16 /avr_de/fcount/fcount_m8.html 60 1.07
17 /avr_en/beginner/SRAM.html 56 1.00
18 /akkuload/de/index.html 55 0.98
19 /avr_de/beginner/hardware.html 55 0.98
20 /avr_de/beginner/register.html 54 0.96
21 /avr_en/signalgen/rectgen_m8.html 50 0.89
22 /avr_de/beginner/rechnen.html 49 0.87
23 /avr_en/stepper/stepper.html 47 0.84
/avr_de/rechteckgen/rectgen_m8.
24 46 0.82
html
25 /avr_de/intro/index.html 45 0.80
Sum 5,602 100.00

To top of page

Top 25 of 160 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,566 15.54
2 /avr_en/beginner/index.html 1,146 11.37
3 /avr_en/index.html 855 8.48
4 /avr_de/beginner/index.html 821 8.15
5 / 773 7.67
6 /avr_en/beginner/RIGHT.html 527 5.23
7 /avr_en/beginner/LEFT.html 473 4.69
8 /avr_de/beginner/rechts.html 467 4.63
9 /avr_de/beginner/links.html 406 4.03
10 /avr_en/ 301 2.99
11 /sitemap_de.html 257 2.55
12 /avr_de/apps.html 160 1.59
13 /index.html 143 1.42
14 /avr_de/interrupts/index.html 139 1.38
15 /sitemap_en.html 132 1.31
16 /avr_en/calc/index.html 121 1.20
17 /avr_de/zeitschleifen/index.html 109 1.08
18 /avr_en/AVR_TUT.html 105 1.04
19 /avr_de/beginner/commands.html 91 0.90
20 /avr_de/avr_tut.html 86 0.85
21 /avr_en/APPS.html 79 0.78
/avr_en/beginner/COMMANDS.
22 62 0.62
html
23 /avr_de/rechnen/index.html 53 0.53
24 /avr_de/ 51 0.51
25 /avr_de/beginner/ports.html 45 0.45
Sum 10,077 100.00

To top of page

Top 25 of 377 external referrers , sorted by number of files

N external referrers times %


1 - 5,242 84.44
2 http://www.mikrocontroller.net/articles/AVR 48 0.77
3 http://www.webring.com/hub?ring=avr 25 0.40
4 http://de.wikipedia.org/wiki/R2R-Netzwerk 25 0.40
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
5 21 0.34
kurs.htm
6 http://avr-asm.tripod.com/ 19 0.31
7 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 18 0.29
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
8 17 0.27
ESC_by1_bz0_bs0.html
9 http://www.rowalt.de/mc/avr/linksd.htm 16 0.26
10 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 16 0.26
http://www.avrfreaks.net/index.php?
11 name=PNphpBB2&file=viewtopic&t=7067 15 0.24
3
12 http://www.educypedia.be/electronics/avr.htm 15 0.24
13 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 15 0.24
14 http://www.dg4fac.de/rechtsunten.html 14 0.23
http://electrons.psychogenic.com/modules/arms/art/3/
15 AVRGCCProgrammingG 13 0.21
uide.php
16 http://www.mikrocontroller.net/articles/Linksammlung 11 0.18
17 http://www.sitidi.net 11 0.18
18 http://www.attiny.com/avrlinks.htm 10 0.16
19 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 9 0.14
20 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 9 0.14
21 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 8 0.13
http://www.avrfreaks.net/index.php?
22 name=PNphpBB2&file=viewtopic&t=3698 8 0.13
8
23 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 7 0.11
24 http://www.dg4fac.de/linksunten.html 7 0.11
25 http://www.elportal.pl/ea/asm_avr_jezyk.html 7 0.11
Sum 6,208 100.00

To top of page

Top 25 of 118 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,405 42.73
2 http://www.google.com 627 19.07
3 http://www.google.at 118 3.59
4 http://www.google.co.in 108 3.28
5 http://www.google.co.uk 77 2.34
6 http://www.google.ch 55 1.67
7 http://www.google.ca 52 1.58
8 http://www.google.nl 52 1.58
9 http://www.google.pl 51 1.55
10 http://www.google.ro 36 1.09
11 http://www.google.com.au 33 1.00
12 http://www.google.fi 31 0.94
13 http://www.google.co.id 28 0.85
14 http://search.live.com 23 0.70
15 http://www.google.se 22 0.67
16 http://www.google.com.br 21 0.64
17 http://www.google.be 21 0.64
http://de.search.yahoo.
18 21 0.64
com
19 http://www.google.com.vn 20 0.61
20 http://www.google.hu 20 0.61
21 http://www.google.gr 20 0.61
http://www.google.com.
22 19 0.58
mx
23 http://www.google.cz 18 0.55
24 http://www.google.hr 18 0.55
25 http://www.google.it 17 0.52
Sum 3,288 100.00

To top of page

Top 25 of 2241 search strings , sorted by number of files

N search strings times %


1 avr tutorial 84 2.55
2 avr 52 1.58
3 avr assembler 51 1.55
4 assembler 37 1.13
5 avr programming 36 1.09
6 attiny13 32 0.97
assembler
7 18 0.55
commands
8 atmega8 18 0.55
9 avr assembly 16 0.49
10 assembler tutorial 15 0.46
11 avr asm 13 0.40
12 gavrasm 13 0.40
13 Assembler 12 0.36
14 AVR programming 12 0.36
15 avr registers 12 0.36
16 programming avr 12 0.36
17 avr asm tutorial 11 0.33
18 avr assembly tutorial 10 0.30
19 atmel assembler 10 0.30
20 avr tutorials 9 0.27
21 r2r dac 9 0.27
22 avr pwm 8 0.24
avr assembler
23 8 0.24
tutorial
24 ATtiny13 8 0.24
25 stk500 8 0.24
Sum 3,288 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 82,629 90.41
2 304 Not changed 7,905 8.65
3 206 Partial information 410 0.45
4 301 Permanently moved 243 0.27

http://www.avr-asm-tutorial.net/weblox_en/2008w48.html (1 of 2)1/20/2009 8:09:24 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 404 File not found 165 0.18


6 300 Multiple choices 18 0.02
7 403 Forbidden 16 0.02
8 405 Method not allowed 3 0.00
9 400 Error in request 1 0.00
Sum 91,390 100.00

To top of page

Top 25 of 66 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 38 23.03
2 /beginner_de.pdf 19 11.52
3 /avr_de/praesentation/favicon.ico 7 4.24
4 /avr_de/praesentation/favicon.gif 7 4.24
/_vti_bin/owssvr.dll?
5 7 4.24
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 6 3.64
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
7 /avr_en/beginner/REGISTER.html/index.html 6 3.64
/_vti_bin/owssvr.dll?
8 3 1.82
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
9 3 1.82
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
10 20la 3 1.82
nguage_files/LEFT.htm
11 /sitemap.xml 2 1.21
/_vti_bin/owssvr.dll?
12 2 1.21
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 2 1.21
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
14 2 1.21
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
15 2 1.21
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
16 /transformers.071011 2 1.21
17 /avr_de/intro/ppt/beispiel10_snd.wav 2 1.21
18 /avr_en/keypad/index.htm 2 1.21
19 /avr_en/stepper/index.htm 2 1.21
20 /avr_en/signalgen/index.htm 2 1.21
21 /gavrasm/v16/LiesMich.Txt 1 0.61
/avr_de/beginner/ports.html/include/functions_common.php?gl_root_path=
22 1 0.61
http://220.134.244.157/xoops/templates_c/id3.txt?
/include/functions_common.php?gl_root_path=http://220.134.244.157/xoop
23 1 0.61
s/templates_c/id3.txt?
/avr_de/beginner/include/functions_common.php?gl_root_path=http://220.
24 1 0.61
134.244.157/xoops/templates_c/id3.txt?
25 /avr_en/beginner/index.html/url%5d 1 0.61
Sum 165 100.00

To top of page

Top 25 of 108 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 49,161 53.79
2 Mozilla/4.0 32,026 35.04
3 Opera/9.62 2,162 2.37
4 Mozilla/4.5 1,178 1.29
5 Opera/9.60 849 0.93
6 Opera/9.61 612 0.67
7 Wget/1.10.2 611 0.67
8 Opera/9.52 589 0.64
9 PageNest 536 0.59
10 Yanga 496 0.54
11 Opera/9.27 324 0.35
12 msnbot/1.1 277 0.30
13 Opera/9.51 258 0.28
Googlebot-
14 228 0.25
Image/1.0
15 Ocelli/1.4 191 0.21
16 Opera/9.50 189 0.21
rdfbot/Nutch-1.0-
17 162 0.18
dev
18 msnbot-media/1.0 115 0.13
19 Opera/9.21 108 0.12
20 Safari/5525.27.1 105 0.11
21 Opera/9.20 98 0.11
22 - 87 0.10
23 Opera/9.24 78 0.09
24 Opera/9.23 76 0.08
25 Yandex/1.01.001 75 0.08
Sum 91,390 100.00

To top of page

Top 25 of 245 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 25,668 28.09
2 MSIE 7.0 16,733 18.31
3 MSIE 6.0 12,784 13.99
4 Firefox/2.0.0.18 4,328 4.74
5 Firefox/3.0.3 2,744 3.00
6 Opera/9.62 2,132 2.33
7 Firefox/3.0.4 2,027 2.22
8 Gecko 1,999 2.19
9 unknown 1,993 2.18
10 Firefox/3.0.1 1,844 2.02
11 Slurp 1,415 1.55
12 HTTrack 3.0x 1,178 1.29
13 Opera/9.60 846 0.93
14 FDM 796 0.87
15 Firefox/3.0 791 0.87
16 Opera/9.61 612 0.67
17 Wget/1.10.2 611 0.67
18 Opera/9.52 589 0.64
19 Firefox/2.0.0.14 512 0.56
20 Firefox/2.0.0.17 480 0.53
21 MSIE 8.0 354 0.39
22 Firefox/3.0.3 349 0.38
23 Opera/9.27 324 0.35
24 Slurp/3.0 301 0.33
25 Firefox/2.0.0.11 291 0.32
Sum 91,390 100.00

To top of page

Top 25 of 45 operating systems , sorted by number of files

N operating systems times %


1 Windows 38,877 42.54
2 Windows NT 5.1 29,818 32.63
3 unknown 6,400 7.00
4 Linux i686 5,318 5.82
5 Windows NT 6.0 4,395 4.81
6 Windows 98 1,735 1.90
7 Windows NT 5.0 1,404 1.54
8 Linux x86_64 702 0.77
9 Mac OS X 10.5 620 0.68
10 Mac OS X 10_5_5 559 0.61
11 Windows NT 5.2 291 0.32
12 Mac OS X 212 0.23
13 Linux 176 0.19
14 Mac OS X 10.4 152 0.17
15 Windows XP 5.1 147 0.16
16 Windows NT 97 0.11
17 Win16 77 0.08
Mac OS X
18 61 0.07
10_4_11
19 Windows 6.0 57 0.06
20 Mac OS X 10_5_4 51 0.06
21 X11 29 0.03
22 Linux 2.6.27.7 28 0.03
23 Macintosh 27 0.03
24 OpenBSD 22 0.02
25 Mac OS X 10_5_2 21 0.02
Sum 91,390 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,677 2.93
2 01 1,922 2.10
3 02 1,723 1.89
4 03 1,384 1.51
5 04 1,568 1.72
6 05 1,781 1.95
7 06 2,324 2.54
8 07 1,926 2.11
9 08 3,219 3.52
10 09 3,946 4.32
11 10 3,956 4.33
12 11 4,795 5.25
13 12 4,648 5.09
14 13 5,620 6.15
15 14 4,341 4.75
16 15 5,130 5.61
17 16 5,698 6.23
18 17 4,568 5.00
19 18 5,322 5.82
20 19 5,136 5.62
21 20 5,287 5.79
22 21 5,999 6.56
23 22 4,450 4.87
24 23 3,970 4.34
Sum 91,390 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w48.html (2 of 2)1/20/2009 8:09:24 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w47

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 47

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5981 IPs and host names , sorted by number of files

N IPs and host names times %


1 67.195.37.109=llf320031.crawl.yahoo.net 627 0.69
2 66.90.73.188=(not found) 611 0.67
3 66.249.72.79=crawl-66-249-72-79.googlebot.com 609 0.67
4 91.205.124.9=(not found) 590 0.65
5 208.111.154.16=crawl2.nat.svl.searchme.com 478 0.53
6 91.144.1.34=(not found) 455 0.50
7 93.134.178.102=mnch-5d86b266.pool.einsundeins.de 337 0.37
8 93.158.148.31=spider11.yandex.ru 286 0.31
9 208.111.154.15=crawl1.nat.svl.searchme.com 253 0.28
10 78.164.150.99=(not found) 240 0.26
11 213.164.111.105=ctv-213-164-111-105.vinita.lt 234 0.26
12 87.173.86.252=p57AD56FC.dip.t-dialin.net 227 0.25
13 78.52.204.231=(not found) 220 0.24
14 83.5.102.28=aanu28.neoplus.adsl.tpnet.pl 217 0.24
15 88.252.133.226=(not found) 195 0.21
16 91.67.186.89=91-67-186-89-dynip.superkabel.de 193 0.21
17 150.214.40.115=jano5.sci.uma.es 189 0.21
18 62.80.98.98=62.80.98.98.not.updated.abovenet.de 181 0.20
19 212.81.24.183=ip-212-081-024-183.static.nextra.sk 170 0.19
20 84.184.69.204=p54B845CC.dip.t-dialin.net 169 0.19
91.89.18.212=HSI-KBW-091-089-018-212.hsi2.kabelbw.
21 164 0.18
de
22 78.8.123.109=dynamic-78-8-123-109.ssp.dialog.net.pl 162 0.18
23 217.236.124.87=pD9EC7C57.dip.t-dialin.net 157 0.17
24 84.133.119.175=p548577AF.dip.t-dialin.net 154 0.17
25 84.184.73.107=p54B8496B.dip.t-dialin.net 152 0.17
Sum 90,931 100.00

To top of page

Top 25 of 5981 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 66.90.73.188=(not found) 18,773 2.02
2 91.205.124.9=(not found) 15,409 1.66
3 141.34.7.112=znzelw1.ifh.de 11,221 1.21
4 67.195.37.109=llf320031.crawl.yahoo.net 10,466 1.13
5 93.134.178.102=mnch-5d86b266.pool.einsundeins.de 9,368 1.01
6 66.249.72.79=crawl-66-249-72-79.googlebot.com 9,292 1.00
7 77.22.123.118=(not found) 8,293 0.89
8 91.144.1.34=(not found) 7,909 0.85
9 79.219.54.233=p4FDB36E9.dip0.t-ipconnect.de 7,806 0.84
10 83.137.79.1=(not found) 6,461 0.70
11 85.181.143.91=e181143091.adsl.alicedsl.de 6,405 0.69
12 87.187.122.214=p57BB7AD6.dip.t-dialin.net 5,954 0.64
13 89.244.183.234=i59F4B7EA.versanet.de 5,112 0.55
14 193.57.156.241=(not found) 4,905 0.53
15 145.254.80.82=dialin-145-254-080-082.pools.arcor-ip.net 4,408 0.48
16 137.226.141.73=theo.weh.RWTH-Aachen.DE 4,211 0.45
17 92.200.13.177=port-92-200-13-177.dynamic.qsc.de 3,994 0.43
18 92.226.143.224=g226143224.adsl.alicedsl.de 3,958 0.43
19 77.184.199.19=hlle-4db8c713.pool.einsundeins.de 3,946 0.43
20 85.158.31.250=gw1.gibz.ch 3,858 0.42
82.212.58.125=HSI-KBW-082-212-058-125.hsi.kabelbw.
21 3,771 0.41
de
22 87.173.86.252=p57AD56FC.dip.t-dialin.net 3,754 0.40
23 213.23.246.226=dialbs-213-023-246-226.static.arcor-ip.net 3,628 0.39
24 85.179.15.66=e179015066.adsl.alicedsl.de 3,621 0.39
25 78.34.37.90=xdsl-78-34-37-90.netcologne.de 3,511 0.38
Sum 927,091 100.00

To top of page

Top 25 of 977 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 122 3.37
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 116 3.21
3 208.111.154.16=crawl2.nat.svl.searchme.com 102 2.82
4 208.111.154.15=crawl1.nat.svl.searchme.com 100 2.76
5 193.47.80.44=crawl8.exabot.com 43 1.19
6 66.235.124.3=crawler5003.ask.com 40 1.11
7 81.52.143.26=natcrawlbloc05.net.m1.fti.net 38 1.05
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 35 0.97
9 81.52.143.16=natcrawlbloc03.net.m1.fti.net 32 0.88
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 32 0.88
11 88.131.106.16=(not found) 30 0.83
12 208.111.154.27=v27.nat.svl.searchme.com 27 0.75
13 38.99.13.125=crawl-4.cuill.com 24 0.66
14 208.111.154.25=v25.nat.svl.searchme.com 22 0.61
15 65.55.209.168=msnbot-65-55-209-168.search.msn.com 19 0.53
16 193.252.149.16=natcrawlbloc04.net.s1.fti.net 18 0.50
17 208.44.234.50=(not found) 17 0.47
67.202.35.13=ec2-67-202-35-13.compute-1.amazonaws.
18 15 0.41
com
19 65.55.232.17=(not found) 14 0.39
20 65.55.209.153=msnbot-65-55-209-153.search.msn.com 14 0.39
21 65.55.209.166=msnbot-65-55-209-166.search.msn.com 13 0.36
22 91.89.18.212=HSI-KBW-091-089-018-212.hsi2.kabelbw.de 11 0.30
23 91.67.186.89=91-67-186-89-dynip.superkabel.de 11 0.30
24 77.79.25.43=hst-25-43.splius.lt 11 0.30
25 72.14.193.69=(not found) 11 0.30
Sum 3,619 100.00

To top of page

Top 25 of 103 countries of origin , sorted by number of files

N countries of origin times %


1 net 24,784 27.26
2 Germany 18,955 20.85
3 (unresolved) 17,632 19.39
4 com 5,487 6.03
5 Poland 2,744 3.02
6 Austria 1,914 2.10
7 Switzerland 1,204 1.32
8 Netherlands 1,140 1.25
9 edu 942 1.04
10 Italy 934 1.03
11 Brazil 748 0.82
12 Belgium 679 0.75
13 Hungary 665 0.73
14 Romania 627 0.69
15 Russian Federation 622 0.68
16 India 622 0.68
17 Mexico 610 0.67
18 United Kingdom 601 0.66
19 Spain 598 0.66
20 Lithuania 581 0.64
21 Canada 573 0.63
22 Slovak Republic 569 0.63
23 Czech Republic 494 0.54
24 Greece 492 0.54
25 Indonesia 490 0.54
Sum 90,931 100.00

To top of page

Top 25 of 107 pathes , sorted by number of files

N pathes times %
1 /common/ 32,417 35.65
2 /avr_gra/ 15,785 17.36
3 / 11,171 12.29
4 /avr_en/beginner/ 3,882 4.27
5 /avr_en/ 2,825 3.11
6 /avr_de/beginner/ 2,698 2.97
7 /avr_de/ 2,674 2.94
8 /avr_en/calc/ 1,845 2.03
9 /avr_de/rechnen/ 1,716 1.89
10 /avr_de/fcount/ 1,320 1.45
11 /avr_de/stepper/ 1,198 1.32
12 /avr_de/praesentation/ 1,070 1.18
13 /avr_en/source/ 1,055 1.16
14 /avr_de/quellen/ 847 0.93
15 /avr_en/keypad/ 817 0.90
16 /avr_en/signalgen/pics/ 736 0.81
17 /avr_de/rechteckgen/bilder/ 726 0.80
18 /gavrasm/ 705 0.78
19 /avr_de/keypad/ 624 0.69
20 /avr_de/zeitschleifen/ 593 0.65
21 /avr_en/stepper/ 585 0.64
22 /avr_de/interrupts/ 447 0.49
23 /privat/magloop/ 326 0.36
24 /gavrasm/v21/ 319 0.35
/avr_de/praesentation/
25 293 0.32
sourcecode/
Sum 90,931 100.00

To top of page

Top 25 of 107 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 178,120 19.21
2 /avr_gra/ 126,357 13.63
3 /avr_de/intro/pdf/ 77,267 8.33
4 / 60,857 6.56
5 /avr_de/fcount/ 51,299 5.53
6 /avr_de/ 42,937 4.63
7 /avr_en/ 38,316 4.13
8 /avr_de/stepper/ 33,088 3.57
9 /avr_en/beginner/ 32,424 3.50
10 /avr_de/beginner/ 25,311 2.73
/avr_de/rechteckgen/
11 19,850 2.14
bilder/
12 /avr_en/signalgen/pics/ 19,571 2.11
13 /gavrasm/v21/ 18,976 2.05
14 /avr_en/calc/ 16,440 1.77
15 /avr_de/rechnen/ 15,969 1.72
16 /privat/magloop/ 15,732 1.70
17 /common/ 15,374 1.66
18 /avr_en/stepper/ 14,668 1.58
19 /avr_de/rechteckgen/ 8,666 0.93
20 /weblox_de/ 8,517 0.92
21 /avr_en/signalgen/ 7,904 0.85
22 /avr_de/intro/ppt/ 7,317 0.79
23 /akkuload/ 7,183 0.77
24 /weblox_en/ 6,464 0.70
25 /avr_en/keypad/ 5,925 0.64
Sum 927,091 100.00

To top of page

Top 25 of 1368 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,876 5.36
2 /avr_gra/RingLogo.jpg 2,556 2.81
/common/knowhow.
3 2,099 2.31
gif
4 /common/app.gif 2,099 2.31
5 /common/akkuload.gif 2,097 2.31
6 /common/beginner.gif 2,092 2.30
7 /common/gavrasm.gif 2,092 2.30
/common/download.
8 2,092 2.30
gif
9 /common/example.gif 2,091 2.30
10 /common/adc.gif 2,090 2.30
11 /avr_gra/stk_lcd.jpg 2,086 2.29
12 /common/r2r.gif 2,086 2.29
/common/gavrasmw.
13 2,086 2.29
gif
14 /common/calc.gif 2,083 2.29
15 /common/clock.gif 2,083 2.29
16 /common/keyb.gif 2,081 2.29
17 /common/hardware.gif 2,079 2.29
18 /index.html 1,509 1.66
19 /avr_en/index.html 1,231 1.35
20 /avr_2313.gif 1,227 1.35
21 /avr_de/index.html 1,203 1.32
22 /dg4fac.gif 1,151 1.27
23 /avr-asm-tutorial.gif 1,138 1.25
24 /common/tn13.gif 1,056 1.16
25 /common/delay.gif 1,056 1.16
Sum 90,931 100.00

To top of page

Top 25 of 1368 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 49,181 5.30
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 42,296 4.56
3 /avr_de/index.html 26,680 2.88
4 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 26,558 2.86
/avr_de/praesentation/Teil_5b_Beispiel01_02.
5 25,855 2.79
pdf
6 /avr_en/index.html 25,178 2.72
7 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 21,126 2.28
8 /avr_2313.gif 20,380 2.20
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 16,495 1.78
10 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 15,535 1.68
11 /dg4fac.gif 12,205 1.32
12 /avr_gra/pwm_simul.jpg 11,413 1.23
13 /avr_gra/r2r_hardware.jpg 11,288 1.22
14 /avr_de/fcount/dscf0004.jpg 10,123 1.09
15 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 9,907 1.07
16 /favicon.ico 9,557 1.03
17 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 9,220 0.99
18 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 9,177 0.99
19 /avr_de/fcount/dscf0005.jpg 8,929 0.96
20 /avr_en/signalgen/pics/rectgen_wiring.jpg 8,922 0.96
21 /avr_de/fcount/dscf0001.jpg 8,420 0.91
22 /avr_de/intro/pdf/Teil1_Prozessor.pdf 8,386 0.90
23 /avr_de/stepper/stepper_v1.gif 8,196 0.88
24 /index.html 7,812 0.84
25 /avr_gra/stk_lcd.jpg 7,184 0.77
Sum 927,091 100.00

To top of page

Top 25 of 400 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,509 7.87
2 /avr_en/index.html 1,231 6.42
3 /avr_de/index.html 1,203 6.27
4 /avr_en/beginner/index.html 669 3.49
5 /avr_en/beginner/RIGHT.html 651 3.39
6 /avr_en/beginner/LEFT.html 645 3.36
7 /avr_de/beginner/index.html 421 2.19
8 /avr_de/beginner/rechts.html 406 2.12
9 /avr_de/beginner/links.html 405 2.11
/avr_en/beginner/HARDWARE.
10 251 1.31
html
11 /avr_en/beginner/REGISTER.html 238 1.24
12 /avr_en/AVR_DAC.html 194 1.01
13 /avr_en/beginner/JUMP.html 188 0.98
14 /avr_de/beginner/hardware.html 175 0.91
15 /avr_en/keypad/keyboard.html 172 0.90
16 /avr_en/beginner/TOOLS.html 168 0.88
17 /avr_de/stepper/stepper.html 166 0.87
18 /avr_de/praesentation/index.html 166 0.87
19 /avr_en/beginner/SRAM.html 162 0.84
20 /avr_de/apps.html 161 0.84
21 /avr_de/avr_dac.html 159 0.83
22 /avr_de/beginner/register.html 153 0.80
23 /avr_en/beginner/CALC.html 149 0.78
24 /avr_de/beginner/sprung.html 143 0.75
25 /avr_de/beginner/ports.html 140 0.73
Sum 19,186 100.00

To top of page

Top 25 of 400 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 26,680 12.22
2 /avr_en/index.html 25,178 11.54
3 /index.html 7,812 3.58
4 /avr_en/beginner/RIGHT.html 4,616 2.11
5 /avr_de/dcf77uhr.html 4,455 2.04
6 /avr_en/beginner/JUMP.html 4,442 2.04
7 /gb_new.html 3,876 1.78
8 /avr_de/beginner/sprung.html 3,801 1.74
9 /avr_en/beginner/CALC.html 3,530 1.62
10 /avr_en/keypad/keyboard.html 3,476 1.59
11 /avr_de/beginner/rechnen.html 2,943 1.35
12 /avr_en/beginner/LEFT.html 2,940 1.35
13 /avr_de/beginner/rechts.html 2,864 1.31
14 /avr_en/AVR_DAC.html 2,837 1.30
15 /avr_de/keypad/keyboard.html 2,753 1.26
/avr_de/rechteckgen/rectgen_m8.
16 2,750 1.26
html
17 /avr_de/avr_dac.html 2,682 1.23
18 /avr_en/beginner/REGISTER.html 2,630 1.20
19 /avr_de/stepper/stepper.html 2,528 1.16
/avr_en/beginner/COMMANDS.
20 2,442 1.12
html
21 /avr_en/signalgen/rectgen_m8.html 2,394 1.10
22 /avr_en/beginner/PDETAIL.html 2,072 0.95
23 /sitemap_de.html 2,060 0.94
24 /avr_en/AVR_ADC500.html 2,040 0.93
25 /avr_en/beginner/SRAM.html 1,976 0.91
Sum 218,264 100.00

To top of page

Top 25 of 379 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,555 18.99
2 /avr_gra/stk_lcd.jpg 2,086 15.50
3 /avr_gra/8515.jpg 561 4.17
4 /avr_gra/r2r_wave.jpg 477 3.55
5 /avr_gra/exp2313g.jpg 407 3.02
6 /avr_gra/avr_isp.jpg 378 2.81
7 /avr_gra/exp_2313.jpg 373 2.77
8 /avr_gra/r2r_sawtooth.jpg 322 2.39
9 /avr_gra/r2r_hardware.jpg 313 2.33
10 /avr_gra/r2r_sawtoothupperbound.jpg 304 2.26
11 /avr_gra/r2r_sawtooth741.jpg 296 2.20
12 /avr_gra/r2r_triangle.jpg 295 2.19
13 /avr_gra/r2r_upperbound.jpg 295 2.19
14 /avr_gra/AT90S8515.jpg 236 1.75
15 /avr_gra/adc8conn.jpg 206 1.53
16 /avr_gra/pwm_simul.jpg 205 1.52
17 /avr_gra/apps.jpg 202 1.50
18 /avr_de/stepper/stepper_sm.jpg 171 1.27
19 /avr_en/signalgen/pics/rectgen_280.jpg 165 1.23
20 /avr_de/stepper/kp4m4-001.jpg 163 1.21
21 /avr_de/stepper/supply.jpg 159 1.18
22 /avr_de/stepper/driver.jpg 156 1.16
23 /avr_de/praesentation/zuendtester.jpg 154 1.14
/avr_de/rechteckgen/bilder/rectgen_280.
24 147 1.09
jpg
25 /akkuload/dscf0030s.jpg 131 0.97
Sum 13,455 100.00

To top of page

Top 25 of 352 GIF-files , sorted by number of files

N GIF-files times %
/common/knowhow.
1 2,099 4.33
gif
2 /common/app.gif 2,099 4.33
3 /common/akkuload.gif 2,097 4.33
4 /common/beginner.gif 2,092 4.32
5 /common/gavrasm.gif 2,092 4.32
/common/download.
6 2,092 4.32
gif
7 /common/example.gif 2,091 4.31
8 /common/adc.gif 2,090 4.31
9 /common/r2r.gif 2,086 4.30
/common/gavrasmw.
10 2,086 4.30
gif
11 /common/calc.gif 2,083 4.30
12 /common/clock.gif 2,083 4.30
13 /common/keyb.gif 2,081 4.29
14 /common/hardware.gif 2,079 4.29
15 /avr_2313.gif 1,227 2.53
16 /dg4fac.gif 1,147 2.37
17 /avr-asm-tutorial.gif 1,138 2.35
18 /common/tn13.gif 1,056 2.18
19 /common/delay.gif 1,056 2.18
20 /common/ints.gif 1,055 2.18
21 /avr_gra/2313.gif 1,008 2.08
22 /avr_gra/exp2313.gif 388 0.80
23 /avr_gra/avr_isp.gif 379 0.78
24 /avr_gra/isp6pin.gif 374 0.77
25 /avr_gra/isp10pin.gif 371 0.77
Sum 48,476 100.00

To top of page

Top 25 of 167 entry pages , sorted by number of files

N entry pages times %


1 /index.html 753 16.82
2 /avr_en/index.html 474 10.59
3 /avr_de/index.html 392 8.76
4 /avr_en/beginner/index.html 202 4.51
5 /avr_en/AVR_DAC.html 122 2.73
6 /avr_de/beginner/index.html 114 2.55
7 /avr_de/stepper/stepper.html 99 2.21
8 /avr_en/beginner/HARDWARE.html 85 1.90
9 /avr_de/avr_dac.html 85 1.90
10 /avr_de/fcount/fcount_m8.html 71 1.59
11 /avr_en/signalgen/rectgen_m8.html 67 1.50
12 /avr_de/keypad/keyboard.html 65 1.45
13 /avr_en/beginner/SRAM.html 65 1.45
14 /avr_en/keypad/keyboard.html 62 1.38
15 /avr_en/AVR_ADC500.html 60 1.34
/avr_de/rechteckgen/rectgen_m8.
16 55 1.23
html
17 /avr_de/beginner/diraus.html 48 1.07
18 /avr_de/rechnen/konversion.html 47 1.05
19 /avr_de/rechnen/multiplikation.html 46 1.03
20 /avr_en/stepper/stepper.html 44 0.98
21 /gb_new.html 42 0.94
22 /avr_de/beginner/hardware.html 38 0.85
23 /avr_de/avr_adc500.html 38 0.85
24 /avr_de/beginner/rechnen.html 36 0.80
25 /avr_de/intro/index.html 35 0.78
Sum 4,477 100.00

To top of page

Top 25 of 205 cheat pages , sorted by number of files

N cheat pages times %


1 919 15.37
2 /index.html 482 8.06
3 /avr_en/index.html 400 6.69
4 /avr_de/index.html 333 5.57
5 /avr_en/beginner/RIGHT.html 142 2.37
6 /avr_en/AVR_DAC.html 125 2.09
7 /avr_en/beginner/HARDWARE.html 105 1.76
8 /avr_de/stepper/stepper.html 90 1.50
9 /avr_de/avr_dac.html 88 1.47
10 /avr_en/keypad/keyboard.html 85 1.42
11 /avr_de/keypad/keyboard.html 80 1.34
12 /avr_de/beginner/rechts.html 76 1.27
13 /avr_en/beginner/SRAM.html 76 1.27
14 /avr_en/beginner/REGISTER.html 71 1.19
15 /avr_en/beginner/JUMP.html 70 1.17
16 /avr_en/signalgen/rectgen_m8.html 67 1.12
17 /avr_en/AVR_ADC500.html 66 1.10
18 /avr_de/beginner/hardware.html 66 1.10
/avr_de/rechteckgen/rectgen_m8.
19 66 1.10
html
20 /avr_de/fcount/fcount_m8.html 66 1.10
21 /avr_de/beginner/diraus.html 52 0.87
22 /avr_de/beginner/sprung.html 50 0.84
23 /avr_de/beginner/rechnen.html 48 0.80
24 /avr_de/avr_adc500.html 48 0.80
25 /avr_de/beginner/register.html 47 0.79
Sum 5,981 100.00

To top of page

Top 25 of 152 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,464 16.09
2 /avr_en/beginner/index.html 1,155 12.69
3 /avr_de/beginner/index.html 729 8.01
4 /avr_en/ 608 6.68
5 / 598 6.57
6 /avr_en/index.html 545 5.99
7 /avr_en/beginner/RIGHT.html 497 5.46
8 /avr_en/beginner/LEFT.html 428 4.70
9 /avr_de/beginner/rechts.html 367 4.03
10 /avr_de/beginner/links.html 269 2.96
11 /sitemap_de.html 188 2.07
12 /index.html 149 1.64
13 /avr_de/apps.html 138 1.52
14 /avr_de/interrupts/index.html 124 1.36
15 /avr_en/AVR_TUT.html 117 1.29
16 /avr_de/zeitschleifen/index.html 111 1.22
17 /avr_en/calc/index.html 100 1.10
18 /avr_de/avr_tut.html 99 1.09
19 /avr_de/ 82 0.90
20 /avr_de/rechnen/index.html 81 0.89
21 /sitemap_en.html 76 0.84
22 /avr_en/APPS.html 75 0.82
23 /avr_de/beginner/commands.html 62 0.68
/avr_en/beginner/COMMANDS.
24 53 0.58
html
/avr_de/rechteckgen/rectgen_m8.
25 50 0.55
html
Sum 9,100 100.00

To top of page

Top 25 of 392 external referrers , sorted by number of files

N external referrers times %


1 - 5,334 83.05
2 http://www.mikrocontroller.net/articles/AVR 38 0.59
3 http://www.webring.com/hub?ring=avr 31 0.48
4 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 22 0.34
5 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 22 0.34
6 http://de.wikipedia.org/wiki/R2R-Netzwerk 18 0.28
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
7 18 0.28
ESC_by1_bz0_bs0.html
8 http://class.ee.iastate.edu/cpre288/lectures.html 17 0.26
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
9 15 0.23
kurs.htm
http://www.avrfreaks.net/index.php?
10 name=PNphpBB2&file=viewtopic&t=7067 14 0.22
3
11 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 13 0.20
12 http://www.dg4fac.de/rechtsunten.html 13 0.20
13 http://www.educypedia.be/electronics/avr.htm 13 0.20
14 http://www.mikrocontroller.net/articles/Linksammlung 13 0.20
15 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 13 0.20
16 http://avr-asm.tripod.com/ 13 0.20
17 http://mathcs.slu.edu/~fritts/csci305_306/links.html 11 0.17
18 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 11 0.17
19 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 11 0.17
20 http://www.dg4fac.de/linksunten.html 10 0.16
21 http://blackstrom.derschwarz.de/avr/avr/index.shtml 10 0.16
http://electrons.psychogenic.com/modules/arms/art/3/
22 AVRGCCProgrammingG 10 0.16
uide.php
23 http://spider.acont.de 10 0.16
24 http://forum.sztvz.hr/showthread.php?t=3639&page=8 10 0.16
25 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 9 0.14
Sum 6,423 100.00

To top of page

Top 25 of 125 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,460 42.53
2 http://www.google.com 648 18.88
3 http://www.google.co.in 111 3.23
4 http://www.google.at 109 3.18
5 http://www.google.co.uk 69 2.01
6 http://www.google.ch 69 2.01
7 http://www.google.pl 59 1.72
8 http://www.google.nl 54 1.57
9 http://www.google.ca 51 1.49
10 http://www.google.se 42 1.22
11 http://www.google.com.au 32 0.93
12 http://www.google.it 31 0.90
13 http://www.google.ro 31 0.90
http://www.google.com.
14 29 0.84
mx
15 http://www.google.co.id 28 0.82
16 http://www.google.com.br 27 0.79
17 http://www.google.fi 25 0.73
18 http://search.live.com 25 0.73
http://de.search.yahoo.
19 21 0.61
com
20 http://search.yahoo.com 21 0.61
21 http://www.google.be 19 0.55
22 http://www.google.com.pk 18 0.52
23 http://www.google.com.tr 18 0.52
24 http://www.google.fr 17 0.50
25 http://www.google.gr 17 0.50
Sum 3,433 100.00

To top of page

Top 25 of 2324 search strings , sorted by number of files

N search strings times %


1 avr tutorial 94 2.74
2 avr assembler 56 1.63
3 avr 41 1.19
4 assembler tutorial 29 0.84
5 avr asm 28 0.82
6 assembler 28 0.82
7 avr assembly 27 0.79
8 avr programming 25 0.73
9 attiny13 25 0.73
10 atmega8 18 0.52
11 avr assembler tutorial 16 0.47
12 avr assembly tutorial 14 0.41
13 atmel tutorial 13 0.38
14 Assembler 11 0.32
15 r2r dac 11 0.32
16 MCUCR 11 0.32
17 AVR assembler 11 0.32
18 gavrasm 11 0.32
19 AVR Assembler 11 0.32
20 68255 11 0.32
schrittmotor
21 10 0.29
steuerung
22 ATtiny13 10 0.29
23 AVR 9 0.26
24 avr beginner 9 0.26
25 r2r network 9 0.26
Sum 3,433 100.00

To top of page

Top 7 of 7 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 80,630 88.67
2 304 Not changed 9,347 10.28
3 206 Partial information 550 0.60
4 301 Permanently moved 212 0.23
5 404 File not found 171 0.19
6 300 Multiple choices 15 0.02
7 403 Forbidden 6 0.01

http://www.avr-asm-tutorial.net/weblox_en/2008w47.html (1 of 2)1/20/2009 8:09:44 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Sum 90,931 100.00

To top of page

Top 25 of 58 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 35 20.47
2 /beginner_de.pdf 19 11.11
3 /avr_de/praesentation/favicon.ico 12 7.02
4 /avr_de/praesentation/favicon.gif 12 7.02
/_vti_bin/owssvr.dll?
5 6 3.51
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 6 3.51
UL=1&ACT=4&BUILD=6254&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
7 20la 3 1.75
nguage.files/LEFT.htm
8 /_vti_inf.html 2 1.17
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
9 20la 2 1.17
nguage_files/LEFT.htm
10 /avr_de/avr_gra/stk_lcd.jpg 2 1.17
11 /avr_de/common/beginner.gif 2 1.17
12 /avr_de/common/tn13.gif 2 1.17
13 /avr_de/common/example.gif 2 1.17
14 /avr_de/common/gavrasm.gif 2 1.17
15 /avr_de/common/delay.gif 2 1.17
16 /avr_de/common/ints.gif 2 1.17
17 /avr_de/common/gavrasmw.gif 2 1.17
18 /avr_de/common/calc.gif 2 1.17
19 /avr_de/common/hardware.gif 2 1.17
20 /avr_de/common/clock.gif 2 1.17
21 /avr_de/common/adc.gif 2 1.17
22 /avr_de/common/keyb.gif 2 1.17
23 /avr_de/common/r2r.gif 2 1.17
24 /avr_de/common/knowhow.gif 2 1.17
25 /avr_de/common/app.gif 2 1.17
Sum 171 100.00

To top of page

Top 25 of 112 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 49,189 54.09
2 Mozilla/4.0 34,121 37.52
3 Opera/9.62 1,634 1.80
4 Opera/9.60 775 0.85
5 Opera/9.61 635 0.70
6 Opera/9.52 602 0.66
7 Yanga 590 0.65
8 Opera/9.51 561 0.62
Googlebot-
9 328 0.36
Image/1.0
10 Yandex/1.01.001 286 0.31
11 msnbot/1.1 285 0.31
12 Opera/9.50 252 0.28
13 Opera/9.25 245 0.27
14 Opera/9.20 134 0.15
15 Java/1.6.0_04 109 0.12
16 Opera/9.27 86 0.09
17 - 84 0.09
18 Opera/9.26 69 0.08
19 Speedy 65 0.07
20 Opera/9.21 65 0.07
21 Mozilla/3.01 53 0.06
22 Opera/7.23 51 0.06
23 Safari/5525.26.12 47 0.05
24 DA 7.0 46 0.05
25 ia_archiver 38 0.04
Sum 90,931 100.00

To top of page

Top 25 of 261 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.4 22,176 24.39
2 MSIE 7.0 19,405 21.34
3 MSIE 6.0 12,111 13.32
4 Firefox/2.0.0.18 4,994 5.49
5 Firefox/3.0.3 3,849 4.23
6 Gecko 2,225 2.45
7 Firefox/3.0.1 2,087 2.30
8 unknown 2,004 2.20
9 Firefox/3.0.4 1,828 2.01
10 Opera/9.62 1,633 1.80
11 Slurp 1,473 1.62
12 Firefox/2.0.0.17 1,274 1.40
13 Firefox/3.0 824 0.91
14 Opera/9.60 775 0.85
15 MSIE 5.0 730 0.80
16 Opera/9.61 635 0.70
17 Gecko/20031021 611 0.67
18 Opera/9.52 588 0.65
19 FDM 581 0.64
20 Opera/9.51 561 0.62
21 Firefox/2.0.0.14 541 0.59
Gecko/2008092816
22 397 0.44
Iceweasel/3.0.3
23 Googlebot-Image/1.0 328 0.36
24 Firefox/2.0.0.16 327 0.36
25 Firefox/2.0.0.11 324 0.36
Sum 90,931 100.00

To top of page

Top 25 of 38 operating systems , sorted by number of files

N operating systems times %


1 Windows 37,921 41.70
2 Windows NT 5.1 29,812 32.79
3 Windows NT 6.0 5,793 6.37
4 unknown 5,630 6.19
5 Linux i686 4,764 5.24
6 Windows NT 5.0 1,270 1.40
7 Linux x86_64 836 0.92
8 Mac OS X 10_5_5 731 0.80
9 Windows NT 4.0 674 0.74
10 FreeBSD i386 641 0.70
11 Mac OS X 10.5 629 0.69
12 Windows 98 436 0.48
13 Windows NT 5.2 404 0.44
14 Win16 286 0.31
Mac OS X
15 207 0.23
10_4_11
16 Linux 200 0.22
17 Windows XP 5.1 156 0.17
18 Mac OS X 10.4 125 0.14
19 Mac OS X 123 0.14
20 SunOS sun4u 65 0.07
21 Windows 6.0 64 0.07
22 Mac OS X Mach-O 55 0.06
23 Linux 2.4.20 i686 22 0.02
24 Linux i686 18 0.02
25 Linux armv6l 18 0.02
Sum 90,931 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,492 2.74
2 01 1,738 1.91
3 02 1,350 1.48
4 03 1,675 1.84
5 04 1,388 1.53
6 05 1,614 1.77
7 06 1,737 1.91
8 07 2,053 2.26
9 08 2,624 2.89
10 09 2,904 3.19
11 10 3,784 4.16
12 11 5,278 5.80
13 12 4,888 5.38
14 13 4,973 5.47
15 14 4,951 5.44
16 15 5,614 6.17
17 16 5,034 5.54
18 17 4,507 4.96
19 18 5,025 5.53
20 19 6,295 6.92
21 20 5,908 6.50
22 21 5,059 5.56
23 22 5,654 6.22
24 23 4,386 4.82
Sum 90,931 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w47.html (2 of 2)1/20/2009 8:09:44 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w46

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 46

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5712 IPs and host names , sorted by number of files

N IPs and host names times %


1 83.160.188.158=atena-2.demon.nl 1,503 1.59
2 84.181.247.241=p54B5F7F1.dip.t-dialin.net 1,262 1.33
3 66.249.72.79=crawl-66-249-72-79.googlebot.com 917 0.97
4 80.91.174.42=undefined.datagroup.com.ua 770 0.81
5 79.234.165.241=p4FEAA5F1.dip0.t-ipconnect.de 758 0.80
6 67.195.37.109=llf320031.crawl.yahoo.net 656 0.69
7 193.144.2.249=pub249.unirioja.es 633 0.67
8 92.80.11.94=(not found) 432 0.46
9 150.214.40.116=jano6.sci.uma.es 393 0.42
10 150.214.40.115=jano5.sci.uma.es 366 0.39
11 202.152.39.154=(not found) 353 0.37
12 208.111.154.16=crawl2.nat.svl.searchme.com 306 0.32
189.143.30.132=dsl-189-143-30-132.prod-infinitum.com.
13 272 0.29
mx
14 24.217.81.115=24-217-81-115.dhcp.stls.mo.charter.com 223 0.24
15 62.47.47.21=62-47-47-21.adsl.highway.telekom.at 221 0.23
16 157.158.164.158=pc164-158.elektron.ds.polsl.pl 212 0.22
17 91.1.70.216=p5B0146D8.dip.t-dialin.net 209 0.22
18 213.179.130.4=(not found) 207 0.22
19 212.77.163.104=(not found) 203 0.21
20 194.39.218.10=http-v.fe.bosch.de 191 0.20
90.29.42.123=ALyon-158-1-19-123.w90-29.abo.wanadoo.
21 179 0.19
fr
22 217.121.228.70=cc937641-a.wsm1.gr.home.nl 173 0.18
23 84.177.198.161=p54B1C6A1.dip.t-dialin.net 171 0.18
24 190.94.28.192=cmodem-28-192.telecable.com.do 167 0.18
25 91.65.84.135=91-65-84-135-dynip.superkabel.de 162 0.17
Sum 94,684 100.00

To top of page

Top 25 of 5712 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 80.91.174.42=undefined.datagroup.com.ua 27,992 2.83
2 202.152.39.154=(not found) 18,356 1.85
3 79.234.165.241=p4FEAA5F1.dip0.t-ipconnect.de 17,640 1.78
4 84.181.247.241=p54B5F7F1.dip.t-dialin.net 16,918 1.71
5 193.144.2.249=pub249.unirioja.es 16,411 1.66
6 66.249.72.79=crawl-66-249-72-79.googlebot.com 10,956 1.11
7 67.195.37.109=llf320031.crawl.yahoo.net 9,301 0.94
8 87.170.67.46=p57AA432E.dip0.t-ipconnect.de 8,820 0.89
9 86.111.51.41=(not found) 6,608 0.67
10 77.22.123.118=(not found) 6,199 0.63
11 217.227.120.91=pD9E3785B.dip.t-dialin.net 5,965 0.60
12 217.94.248.191=pD95EF8BF.dip.t-dialin.net 5,777 0.58
13 130.236.33.215=mkrtr.ikp.liu.se 5,341 0.54
14 195.200.34.50=(not found) 5,301 0.54
15 91.4.102.47=p5B04662F.dip.t-dialin.net 4,854 0.49
78.42.236.34=HSI-KBW-078-042-236-034.hsi3.kabel-badenwuerttemberg.
16 4,520 0.46
de
17 85.179.98.155=e179098155.adsl.alicedsl.de 4,443 0.45
18 88.131.106.16=(not found) 4,412 0.45
19 87.158.124.148=p579E7C94.dip.t-dialin.net 4,284 0.43
20 80.86.176.226=gateway.ingolstadt.de 4,235 0.43
21 91.1.70.216=p5B0146D8.dip.t-dialin.net 4,133 0.42
22 134.91.90.91=damar.uni-duisburg.de 4,044 0.41
23 217.237.83.182=pD9ED53B6.dip.t-dialin.net 3,958 0.40
24 91.4.225.43=p5B04E12B.dip.t-dialin.net 3,592 0.36
25 92.50.105.126=(not found) 3,562 0.36
Sum 990,274 100.00

To top of page

Top 25 of 1035 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 103 2.77
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 101 2.71
3 208.111.154.16=crawl2.nat.svl.searchme.com 46 1.23
4 208.111.154.15=crawl1.nat.svl.searchme.com 43 1.15
5 88.131.106.16=(not found) 39 1.05
6 81.52.143.26=natcrawlbloc05.net.m1.fti.net 37 0.99
7 81.52.143.16=natcrawlbloc03.net.m1.fti.net 37 0.99
8 193.252.149.15=natcrawlbloc02.net.s1.fti.net 34 0.91
9 193.47.80.44=crawl8.exabot.com 33 0.89
10 81.52.143.15=natcrawlbloc01.net.m1.fti.net 28 0.75
11 74.6.22.161=llf520075.crawl.yahoo.net 22 0.59
12 74.6.22.157=llf520070.crawl.yahoo.net 20 0.54
13 212.254.176.2=adsl-176-2-fixip.tiscali.ch 19 0.51
14 65.55.209.168=msnbot-65-55-209-168.search.msn.com 19 0.51
15 65.55.209.151=msnbot-65-55-209-151.search.msn.com 18 0.48
16 193.252.149.16=natcrawlbloc04.net.s1.fti.net 16 0.43
17 202.160.178.140=lj910105.crawl.yahoo.net 16 0.43
18 65.55.209.153=msnbot-65-55-209-153.search.msn.com 14 0.38
19 92.80.11.94=(not found) 13 0.35
20 202.142.166.4=202-142-166-4.multi.net.pk 13 0.35
21 72.14.199.45=(not found) 13 0.35
22 221.221.7.15=(not found) 13 0.35
23 208.44.234.50=(not found) 13 0.35
24 74.6.17.167=llf520193.crawl.yahoo.net 13 0.35
24.217.81.115=24-217-81-115.dhcp.stls.mo.charter.
25 12 0.32
com
Sum 3,725 100.00

To top of page

Top 25 of 94 countries of origin , sorted by number of files

N countries of origin times %


1 net 25,791 27.24
2 Germany 20,528 21.68
3 (unresolved) 16,444 17.37
4 com 6,533 6.90
5 Netherlands 2,645 2.79
6 Austria 2,324 2.45
7 Poland 2,068 2.18
8 Spain 1,708 1.80
9 Italy 1,191 1.26
10 Switzerland 1,070 1.13
11 Mexico 887 0.94
12 Ukraine 852 0.90
13 Hungary 716 0.76
14 Czech Republic 666 0.70
15 edu 645 0.68
16 Australia 629 0.66
17 Sweden 585 0.62
18 Norway 553 0.58
19 India 505 0.53
20 Japan 505 0.53
21 Greece 477 0.50
22 Romania 440 0.46
23 Indonesia 425 0.45
24 Brazil 424 0.45
25 United Kingdom 394 0.42
Sum 94,684 100.00

To top of page

Top 25 of 129 pathes , sorted by number of files

N pathes times %
1 /common/ 32,277 34.09
2 /avr_gra/ 16,408 17.33
3 / 10,797 11.40
4 /avr_en/beginner/ 4,061 4.29
5 /avr_de/beginner/ 3,093 3.27
6 /avr_de/ 2,928 3.09
7 /avr_en/ 2,901 3.06
8 /avr_en/calc/ 2,064 2.18
9 /avr_de/rechnen/ 1,508 1.59
10 /avr_de/fcount/ 1,495 1.58
11 /avr_de/quellen/ 1,244 1.31
12 /avr_de/stepper/ 1,217 1.29
13 /avr_en/source/ 1,207 1.27
14 /avr_de/praesentation/ 1,197 1.26
15 /avr_en/keypad/ 990 1.05
16 /avr_en/stepper/ 815 0.86
17 /avr_en/signalgen/pics/ 746 0.79
18 /avr_de/keypad/ 739 0.78
19 /gavrasm/ 698 0.74
/avr_de/rechteckgen/
20 687 0.73
bilder/
21 /avr_de/zeitschleifen/ 646 0.68
22 /avr_de/interrupts/ 534 0.56
23 /akkuload/ 342 0.36
24 /privat/magloop/ 337 0.36
25 /cq-dl/teil4/ 314 0.33
Sum 94,684 100.00

To top of page

Top 25 of 129 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 194,742 19.67
2 /avr_gra/ 126,809 12.81
3 /avr_de/intro/pdf/ 71,612 7.23
4 / 58,360 5.89
5 /avr_de/fcount/ 55,717 5.63
6 /avr_de/ 43,152 4.36
7 /avr_en/ 38,587 3.90
8 /avr_en/beginner/ 33,826 3.42
9 /avr_de/stepper/ 32,394 3.27
10 /avr_de/beginner/ 29,724 3.00
11 /gavrasm/v21/ 22,136 2.24
12 /avr_en/stepper/ 19,974 2.02
13 /avr_en/signalgen/pics/ 19,654 1.98
/avr_de/rechteckgen/
14 18,407 1.86
bilder/
15 /avr_en/calc/ 17,973 1.81
16 /privat/magloop/ 16,652 1.68
17 /common/ 14,945 1.51
18 /avr_de/rechteckgen/ 13,349 1.35
19 /avr_de/rechnen/ 13,214 1.33
20 /weblox_de/ 12,464 1.26
21 /weblox_en/ 11,852 1.20
22 /avr_de/intro/ppt/ 11,483 1.16
23 /avr_en/signalgen/ 9,052 0.91
24 /akkuload/ 8,143 0.82
25 /avr_en/keypad/ 6,969 0.70
Sum 990,274 100.00

To top of page

Top 25 of 1417 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,673 4.94
2 /avr_gra/RingLogo.jpg 2,495 2.64
3 /common/app.gif 2,095 2.21
/common/download.
4 2,087 2.20
gif
5 /common/akkuload.gif 2,086 2.20
6 /common/example.gif 2,081 2.20
7 /common/calc.gif 2,081 2.20
/common/gavrasmw.
8 2,074 2.19
gif
9 /common/adc.gif 2,073 2.19
10 /common/keyb.gif 2,073 2.19
/common/knowhow.
11 2,073 2.19
gif
12 /avr_gra/stk_lcd.jpg 2,071 2.19
13 /common/gavrasm.gif 2,071 2.19
14 /common/hardware.gif 2,070 2.19
15 /common/clock.gif 2,069 2.19
16 /common/beginner.gif 2,068 2.18
17 /common/r2r.gif 2,063 2.18
18 /index.html 1,435 1.52
19 /avr_de/index.html 1,200 1.27
20 /avr_en/index.html 1,196 1.26
21 /avr_2313.gif 1,178 1.24
22 /dg4fac.gif 1,091 1.15
23 /avr_gra/2313.gif 1,083 1.14
24 /avr-asm-tutorial.gif 1,083 1.14
25 /common/delay.gif 1,074 1.13
Sum 94,684 100.00

To top of page

Top 25 of 1417 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 59,356 5.99
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 36,174 3.65
3 /avr_de/index.html 26,378 2.66
/avr_de/praesentation/Teil_5b_Beispiel01_02.
4 25,443 2.57
pdf
5 /avr_en/index.html 24,189 2.44
6 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 22,823 2.30
7 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 22,773 2.30
8 /avr_2313.gif 18,920 1.91
9 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 18,231 1.84
10 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 18,107 1.83
11 /avr_gra/pwm_simul.jpg 12,049 1.22
12 /dg4fac.gif 11,376 1.15
13 /avr_de/fcount/dscf0004.jpg 11,024 1.11
14 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 10,489 1.06
15 /avr_gra/r2r_hardware.jpg 9,786 0.99
16 /avr_de/fcount/dscf0005.jpg 9,272 0.94
17 /favicon.ico 9,150 0.92
18 /avr_en/signalgen/pics/rectgen_wiring.jpg 8,958 0.90
19 /avr_de/fcount/dscf0001.jpg 8,895 0.90
20 /avr_de/intro/pdf/Teil1_Prozessor.pdf 8,690 0.88
21 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 8,568 0.87
22 /avr_de/rechteckgen/rectgen_m8.xls 8,403 0.85
23 /avr_gra/exp2313.gif 8,032 0.81
24 /avr_de/stepper/stepper_v1.gif 8,003 0.81
25 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 7,963 0.80
Sum 990,274 100.00

To top of page

Top 25 of 429 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,435 6.93
2 /avr_de/index.html 1,200 5.79
3 /avr_en/index.html 1,196 5.78
4 /avr_en/beginner/index.html 700 3.38
5 /avr_en/beginner/RIGHT.html 698 3.37
6 /avr_en/beginner/LEFT.html 697 3.37
7 /avr_de/beginner/index.html 470 2.27
8 /avr_de/beginner/links.html 456 2.20
9 /avr_de/beginner/rechts.html 451 2.18
/avr_en/beginner/HARDWARE.
10 267 1.29
html
11 /avr_en/beginner/REGISTER.html 239 1.15
12 /avr_de/beginner/hardware.html 197 0.95
13 /avr_en/beginner/JUMP.html 190 0.92
14 /avr_en/keypad/keyboard.html 187 0.90
15 /avr_en/AVR_DAC.html 166 0.80
16 /avr_de/apps.html 164 0.79
17 /avr_en/beginner/TOOLS.html 163 0.79
18 /avr_en/beginner/SRAM.html 162 0.78
19 /avr_de/avr_dac.html 162 0.78
20 /avr_de/stepper/stepper.html 162 0.78
21 /avr_de/beginner/sprung.html 161 0.78
22 /avr_en/AVR_ADC500.html 160 0.77
23 /avr_de/beginner/ports.html 159 0.77
24 /avr_de/praesentation/index.html 157 0.76
25 /avr_de/beginner/register.html 157 0.76
Sum 20,708 100.00

To top of page

Top 25 of 429 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 26,378 11.10
2 /avr_en/index.html 24,189 10.18
3 /index.html 7,264 3.06
4 /avr_en/beginner/RIGHT.html 4,872 2.05
5 /avr_en/beginner/JUMP.html 4,482 1.89
6 /avr_de/beginner/sprung.html 4,466 1.88
7 /gb_new.html 4,394 1.85
8 /avr_de/dcf77uhr.html 3,969 1.67
9 /avr_en/keypad/keyboard.html 3,776 1.59
10 /avr_en/beginner/CALC.html 3,276 1.38
11 /avr_de/beginner/rechnen.html 3,186 1.34
12 /avr_de/beginner/rechts.html 3,167 1.33
13 /avr_en/beginner/LEFT.html 3,120 1.31
14 /avr_en/beginner/REGISTER.html 2,808 1.18
15 /avr_de/keypad/keyboard.html 2,772 1.17
16 /avr_en/beginner/PDETAIL.html 2,604 1.10
17 /avr_de/beginner/pdetail.html 2,488 1.05
18 /avr_de/avr_dac.html 2,484 1.05
19 /avr_en/AVR_ADC500.html 2,465 1.04
20 /avr_de/stepper/stepper.html 2,448 1.03
/avr_en/beginner/COMMANDS.
21 2,429 1.02
html
/avr_de/rechteckgen/rectgen_m8.
22 2,420 1.02
html
23 /avr_de/beginner/commands.html 2,398 1.01
24 /avr_en/signalgen/rectgen_m8.html 2,370 1.00
25 /avr_en/AVR_DAC.html 2,350 0.99
Sum 237,613 100.00

To top of page

Top 25 of 347 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,495 18.28
2 /avr_gra/stk_lcd.jpg 2,071 15.18
3 /avr_gra/8515.jpg 536 3.93
4 /avr_gra/exp2313g.jpg 443 3.25
5 /avr_gra/avr_isp.jpg 437 3.20
6 /avr_gra/exp_2313.jpg 430 3.15
7 /avr_gra/r2r_wave.jpg 313 2.29
8 /avr_gra/r2r_sawtooth.jpg 297 2.18
9 /avr_gra/r2r_triangle.jpg 291 2.13
10 /avr_gra/r2r_hardware.jpg 290 2.13
11 /avr_gra/r2r_upperbound.jpg 289 2.12
12 /avr_gra/r2r_sawtoothupperbound.jpg 286 2.10
13 /avr_gra/r2r_sawtooth741.jpg 286 2.10
14 /avr_gra/AT90S8515.jpg 274 2.01
15 /avr_gra/adc8conn.jpg 229 1.68
16 /avr_gra/pwm_simul.jpg 229 1.68
17 /avr_gra/apps.jpg 228 1.67
18 /avr_de/stepper/stepper_sm.jpg 174 1.28
/avr_en/signalgen/pics/rectgen_280.
19 169 1.24
jpg
20 /avr_de/stepper/kp4m4-001.jpg 163 1.19
21 /avr_de/stepper/supply.jpg 161 1.18
22 /akkuload/dscf0030s.jpg 160 1.17
23 /avr_de/stepper/driver.jpg 158 1.16
24 /avr_de/praesentation/zuendtester.jpg 145 1.06
25 /avr_gra/stk200lcd.jpg 139 1.02
Sum 13,647 100.00

To top of page

Top 25 of 333 GIF-files , sorted by number of files

N GIF-files times %
1 /common/app.gif 2,095 4.24
/common/download.
2 2,087 4.22
gif
3 /common/akkuload.gif 2,086 4.22
4 /common/example.gif 2,081 4.21
5 /common/calc.gif 2,081 4.21
/common/gavrasmw.
6 2,074 4.20
gif
7 /common/adc.gif 2,073 4.20
8 /common/keyb.gif 2,073 4.20
/common/knowhow.
9 2,073 4.20
gif
10 /common/gavrasm.gif 2,071 4.19
11 /common/hardware.gif 2,070 4.19
12 /common/clock.gif 2,069 4.19
13 /common/beginner.gif 2,068 4.19
14 /common/r2r.gif 2,063 4.18
15 /avr_2313.gif 1,178 2.38
16 /dg4fac.gif 1,091 2.21
17 /avr_gra/2313.gif 1,083 2.19
18 /avr-asm-tutorial.gif 1,083 2.19
19 /common/delay.gif 1,074 2.17
20 /common/ints.gif 1,072 2.17
21 /common/tn13.gif 1,067 2.16
22 /avr_gra/exp2313.gif 451 0.91
23 /avr_gra/avr_isp.gif 435 0.88
24 /avr_gra/isp6pin.gif 434 0.88
25 /avr_gra/isp10pin.gif 434 0.88
Sum 49,400 100.00

To top of page

Top 25 of 175 entry pages , sorted by number of files

N entry pages times %


1 /index.html 704 15.96
2 /avr_en/index.html 467 10.58
3 /avr_de/index.html 383 8.68
4 /avr_en/beginner/index.html 219 4.96
5 /avr_de/beginner/index.html 143 3.24
6 /avr_en/AVR_DAC.html 93 2.11
7 /avr_de/avr_dac.html 93 2.11
8 /avr_en/beginner/HARDWARE.html 88 1.99
9 /avr_de/stepper/stepper.html 86 1.95
10 /avr_de/fcount/fcount_m8.html 75 1.70
11 /avr_en/keypad/keyboard.html 70 1.59
12 /avr_en/AVR_ADC500.html 69 1.56
/avr_de/rechteckgen/rectgen_m8.
13 68 1.54
html
14 /avr_en/signalgen/rectgen_m8.html 64 1.45
15 /avr_de/keypad/keyboard.html 56 1.27
16 /gb_new.html 54 1.22
17 /avr_de/beginner/hardware.html 47 1.07
18 /avr_en/stepper/stepper.html 46 1.04
19 /avr_de/rechnen/konversion.html 46 1.04
20 /avr_de/intro/index.html 43 0.97
21 /avr_en/beginner/REGISTER.html 42 0.95
22 /avr_de/beginner/diraus.html 41 0.93
23 /avr_en/beginner/SRAM.html 37 0.84
24 /avr_de/avr_adc500.html 36 0.82
25 /avr_de/beginner/werkzeuge.html 36 0.82
Sum 4,412 100.00

To top of page

Top 25 of 214 cheat pages , sorted by number of files

N cheat pages times %


1 796 13.94
2 /index.html 440 7.70
3 /avr_de/index.html 352 6.16
4 /avr_en/index.html 343 6.00
5 /avr_en/beginner/RIGHT.html 124 2.17
6 /avr_en/beginner/HARDWARE.html 117 2.05
7 /avr_en/AVR_DAC.html 105 1.84
8 /avr_en/keypad/keyboard.html 101 1.77
9 /avr_de/avr_dac.html 95 1.66
10 /avr_de/beginner/rechts.html 91 1.59
11 /avr_de/stepper/stepper.html 90 1.58
12 /avr_en/AVR_ADC500.html 81 1.42
13 /avr_en/beginner/REGISTER.html 80 1.40
14 /avr_de/keypad/keyboard.html 75 1.31
15 /avr_de/fcount/fcount_m8.html 75 1.31
16 /avr_de/beginner/hardware.html 62 1.09
17 /avr_en/signalgen/rectgen_m8.html 62 1.09
18 /avr_en/beginner/SRAM.html 60 1.05
19 /avr_de/beginner/diraus.html 57 1.00
20 /avr_en/beginner/JUMP.html 57 1.00
/avr_de/rechteckgen/rectgen_m8.
21 53 0.93
html
22 /avr_de/beginner/werkzeuge.html 52 0.91
23 /akkuload/de/index.html 51 0.89
24 /gb_new.html 51 0.89
25 /avr_de/beginner/sprung.html 50 0.88
Sum 5,712 100.00

To top of page

Top 25 of 158 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,618 15.51
2 /avr_en/beginner/index.html 1,205 11.55
3 /avr_de/beginner/index.html 812 7.79
4 /avr_en/index.html 681 6.53
5 / 594 5.70
6 /avr_en/ 557 5.34
7 /avr_en/beginner/RIGHT.html 527 5.05
8 /sitemap_de.html 466 4.47
9 /avr_de/beginner/rechts.html 431 4.13
10 /avr_en/beginner/LEFT.html 387 3.71
11 /sitemap_en.html 297 2.85
12 /avr_de/beginner/links.html 270 2.59
13 /index.html 182 1.74
14 /avr_de/interrupts/index.html 139 1.33
15 /weblox_de/index.html 135 1.29
16 /weblox_en/index.html 134 1.28
17 /avr_de/zeitschleifen/index.html 133 1.28
18 /avr_de/apps.html 122 1.17
19 /avr_de/avr_tut.html 114 1.09
20 /avr_en/calc/index.html 106 1.02
21 /avr_en/AVR_TUT.html 104 1.00
22 /avr_de/ 94 0.90
23 /avr_en/APPS.html 75 0.72
/avr_de/beginner/commands.
24 71 0.68
html
25 /avr_de/rechnen/index.html 54 0.52
Sum 10,430 100.00

To top of page

Top 25 of 370 external referrers , sorted by number of files

N external referrers times %


1 - 5,653 84.06
2 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 42 0.62
3 http://www.mikrocontroller.net/articles/AVR 41 0.61
4 http://www.webring.com/hub?ring=avr 32 0.48
5 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 28 0.42
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
6 25 0.37
kurs.htm
7 http://www.dg4fac.de/linksunten.html 20 0.30
8 http://de.wikipedia.org/wiki/R2R-Netzwerk 20 0.30
9 http://www.educypedia.be/electronics/avr.htm 19 0.28
http://www.avrfreaks.net/index.php?
10 name=PNphpBB2&file=viewtopic&t=7067 16 0.24
3
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
11 16 0.24
ESC_by1_bz0_bs0.html
12 http://circuit.lt/?section=sch&page=avr.isp.lpt 15 0.22
http://electrons.psychogenic.com/modules/arms/art/3/
13 AVRGCCProgrammingG 13 0.19
uide.php
14 http://www.dg4fac.de/rechtsunten.html 13 0.19
http://74.125.93.104/translate_c?hl=es&sl=en&u=http://www.avr-asm-tuto
rial.net/avr_en/&prev=/search%3Fq%3DAVR%2B%2B%2BASEMBLER%
15 13 0.19
26hl%3Des&usg
=ALkJrhgpzJltZc9EpUy8mLuwFAZSulrifg
16 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 13 0.19
17 http://www.rowalt.de/mc/avr/linksd.htm 12 0.18
18 http://s-huehn.de/elektronik/links.htm 12 0.18
19 http://avr-asm.tripod.com/ 11 0.16
20 http://www.mikrocontroller.net/articles/Linksammlung 11 0.16
21 http://mathcs.slu.edu/~fritts/csci305_306/labs/lab7.html 11 0.16
22 http://www.mikrocontroller.net/topic/116443 11 0.16
23 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 10 0.15
24 http://www.tutorialzone.de/tutorials/AVR_Assembler_Tutorial/1884 10 0.15
25 http://home.arcor.de/olaf.petera/avr/links.html 10 0.15
Sum 6,725 100.00

To top of page

Top 25 of 115 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,449 43.61
2 http://www.google.com 642 19.32
3 http://www.google.at 85 2.56
4 http://www.google.co.in 79 2.38
http://www.google.com.
5 68 2.05
au
6 http://www.google.co.uk 67 2.02
7 http://www.google.ch 61 1.84
8 http://www.google.nl 50 1.50
9 http://www.google.pl 42 1.26
10 http://www.google.ca 32 0.96
11 http://www.google.co.id 30 0.90
12 http://www.google.se 30 0.90
13 http://www.google.it 28 0.84
14 http://search.live.com 24 0.72
15 http://www.google.hu 22 0.66
http://www.google.com.
16 22 0.66
pk
17 http://www.google.es 21 0.63
18 http://www.google.ro 21 0.63
19 http://search.yahoo.com 20 0.60
http://www.google.com.
20 20 0.60
br
21 http://www.google.fr 20 0.60
22 http://www.google.no 20 0.60
23 http://www.google.cz 19 0.57
24 http://www.google.co.za 19 0.57
25 http://www.google.com.tr 18 0.54
Sum 3,323 100.00

To top of page

Top 25 of 2234 search strings , sorted by number of files

N search strings times %


1 avr tutorial 84 2.53
2 avr assembler 70 2.11
3 avr 45 1.35
4 avr programming 37 1.11
5 attiny13 33 0.99
6 assembler 33 0.99
7 avr asm 24 0.72
8 avr assembly 18 0.54
assembler
9 14 0.42
programmierung
10 avr asm tutorial 13 0.39
11 assembler tutorial 13 0.39
12 atmega assembler 12 0.36
13 avr assembler tutorial 12 0.36
14 AVR tutorial 12 0.36
15 atmel assembler 12 0.36
16 atmel tutorial 11 0.33
17 atmega8 10 0.30
18 ATtiny13 10 0.30
19 assembler commands 10 0.30
20 r2r network 10 0.30
21 avr keypad 9 0.27
22 stk500 9 0.27
23 gavrasm 9 0.27
24 wavrasm 8 0.24
25 Attiny13 8 0.24
Sum 3,323 100.00

To top of page

Top 10 of 10 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 83,390 88.07
2 304 Not changed 10,455 11.04
3 206 Partial information 412 0.44
4 404 File not found 204 0.22

http://www.avr-asm-tutorial.net/weblox_en/2008w46.html (1 of 2)1/20/2009 8:10:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 301 Permanently moved 185 0.20


6 300 Multiple choices 21 0.02
7 403 Forbidden 9 0.01
8 405 Method not allowed 6 0.01
9 401 Not authorized 1 0.00
10 xxx Unknown error 1 0.00
Sum 94,684 100.00

To top of page

Top 25 of 62 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 49 24.02
2 /beginner_de.pdf 26 12.75
3 /avr_de/praesentation/favicon.ico 14 6.86
4 /avr_de/praesentation/favicon.gif 14 6.86
/_vti_bin/owssvr.dll?
5 8 3.92
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
6 8 3.92
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
7 /avr_de/intro/ppt/beispiel10_snd.wav 5 2.45
/avr_en/beginner/COMMANDS.html/index.php?page=http://www.
8 fundraising4c 4 1.96
harity.org.uk/unisaber/index.php/bo.do???
/avr_en/beginner/COMMAND%20.../index.php?page=http://www.
9 fundraising4c 4 1.96
harity.org.uk/unisaber/index.php/bo.do???
/_vti_bin/owssvr.dll?
10 4 1.96
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
11 4 1.96
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
12 3 1.47
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
13 3 1.47
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/_vti_bin/owssvr.dll?
14 3 1.47
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
15 3 1.47
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
16 /avr_en/quellen/schrittmotor_v1.asm 2 0.98
17 /avr_en/stepper/schrittmotor_v1.html 2 0.98
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
18 20AVR-Assemble 2 0.98
r-Dateien/links.htm
19 /SlurpConfirm404.htm 2 0.98
20 /avr_en/keypad/keyboard/html 2 0.98
/avr_en/beginner/COMMANDS.html//?page=http://www.easysupportdesk.
21 com/c 1 0.49
ache/id.txt???
/avr_en/beginner/COMMAND%20...//?page=http://www.easysupportdesk.
22 com/c 1 0.49
ache/id.txt???
/avr_en/beginner/Pemula's%20pengenalan%20untuk%20AVR%20assembler
23 %20bah 1 0.49
asa4_files/translate_c.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
24 20AVR-Assemble 1 0.49
r-Dateien/rechts.htm
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
25 20AVR-Assemble 1 0.49
r2-Dateien/links.htm
Sum 204 100.00

To top of page

Top 25 of 118 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 47,867 50.55
2 Mozilla/4.0 35,920 37.94
3 Mozilla/4.5 2,000 2.11
4 Opera/9.62 1,480 1.56
5 Mozilla/3.0 1,477 1.56
6 Opera/9.61 767 0.81
7 Teleport Pro/1.29 738 0.78
8 Opera/9.60 558 0.59
9 Opera/9.52 543 0.57
10 msnbot/1.1 313 0.33
11 Googlebot-Image/1.0 295 0.31
12 Opera/9.26 290 0.31
13 Opera/9.24 245 0.26
14 Opera/9.51 220 0.23
ia_archiver-web.archive.
15 184 0.19
org
16 Opera/9.50 162 0.17
17 Speedy 142 0.15
18 Opera/9.27 133 0.14
19 Opera/9.25 120 0.13
20 Opera/9.10 106 0.11
21 Yandex/1.01.001 92 0.10
22 msnbot-media/1.0 90 0.10
23 - 74 0.08
24 msnbot-media/1.1 67 0.07
25 Microsoft 63 0.07
Sum 94,684 100.00

To top of page

Top 25 of 256 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.3 19,933 21.05
2 MSIE 7.0 17,935 18.94
3 MSIE 6.0 15,191 16.04
4 Firefox/3.0.4 5,824 6.15
5 Firefox/2.0.0.17 3,411 3.60
6 Firefox/3.0.1 2,758 2.91
7 Gecko 2,015 2.13
8 HTTrack 3.0x 2,000 2.11
9 Firefox/2.0.0.18 1,676 1.77
10 Opera/9.62 1,480 1.56
11 Indy Library 1,473 1.56
12 Slurp 1,355 1.43
13 Firefox/3.0.3 1,164 1.23
14 unknown 1,046 1.10
15 FDM 796 0.84
16 Opera/9.61 767 0.81
17 Firefox/3.0 754 0.80
18 Pro/1.29 738 0.78
19 MSIE 5.0 687 0.73
20 Googlebot/2.1 616 0.65
21 Opera/9.60 554 0.59
22 Opera/9.52 534 0.56
23 Firefox/2.0.0.14 502 0.53
24 Firefox/2.0.0.6 499 0.53
25 Firefox/3.0.4 445 0.47
Sum 94,684 100.00

To top of page

Top 25 of 41 operating systems , sorted by number of files

N operating systems times %


1 Windows 37,124 39.21
2 Windows NT 5.1 32,246 34.06
3 unknown 7,291 7.70
4 Linux i686 5,020 5.30
5 Windows NT 6.0 4,644 4.90
6 Windows 98 2,724 2.88
7 Windows NT 5.0 1,461 1.54
8 Linux x86_64 942 0.99
9 Windows NT 4.0 609 0.64
10 Mac OS X 10_5_5 570 0.60
11 Mac OS X 10.5 364 0.38
12 Linux 354 0.37
13 Windows NT 5.2 293 0.31
14 Mac OS X 169 0.18
15 Mac OS X 10.4 169 0.18
16 Windows XP 5.1 136 0.14
17 Mac OS X 10_4_11 110 0.12
18 Linux i686 108 0.11
19 Win16 94 0.10
20 Windows 6.0 58 0.06
21 Kubuntu 34 0.04
22 Windows 2000 5.0 33 0.03
23 Mac OS X 10_5_4 23 0.02
24 Mac OS X 10_5_2 21 0.02
Linux 2.6.21.5-dix
25 17 0.02
i686
Sum 94,684 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 3,461 3.66
2 01 2,050 2.17
3 02 1,793 1.89
4 03 1,384 1.46
5 04 1,402 1.48
6 05 1,102 1.16
7 06 1,061 1.12
8 07 2,239 2.36
9 08 3,057 3.23
10 09 4,054 4.28
11 10 4,155 4.39
12 11 4,915 5.19
13 12 4,834 5.11
14 13 5,228 5.52
15 14 5,949 6.28
16 15 5,224 5.52
17 16 4,919 5.20
18 17 5,143 5.43
19 18 5,661 5.98
20 19 5,544 5.86
21 20 5,758 6.08
22 21 6,283 6.64
23 22 5,604 5.92
24 23 3,864 4.08
Sum 94,684 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w46.html (2 of 2)1/20/2009 8:10:05 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w45

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 45

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 6012 IPs and host names , sorted by number of files

N IPs and host names times %


1 91.205.124.9=(not found) 910 0.95
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 873 0.91
3 83.160.188.158=atena-2.demon.nl 779 0.81
4 67.195.37.109=llf320031.crawl.yahoo.net 629 0.65
5 89.16.140.231=cable-89-16-140-231.cust.blue-cable.de 624 0.65
6 78.111.65.140=(not found) 525 0.55
7 89.61.201.7=Zc907.z.pppool.de 509 0.53
8 70.50.6.234=bas18-toronto12-1177683690.dsl.bell.ca 466 0.48
9 202.153.240.100=dsl-153.240-100.static.indo.net.id 402 0.42
10 121.227.251.52=52.251.227.121.broad.sz.js.dynamic.163data.com.cn 391 0.41
11 190.161.18.227=(not found) 377 0.39
12 84.133.76.147=p54854C93.dip.t-dialin.net 365 0.38
13 87.193.252.210=port-87-193-252-210.static.qsc.de 337 0.35
14 89.110.221.192=pttnet221-192.ptt.rs 290 0.30
15 203.160.1.71=localhost 279 0.29
16 78.46.78.40=crawlh004.ayell.org 245 0.25
17 93.158.148.31=spider11.yandex.ru 234 0.24
18 84.149.74.231=p54954AE7.dip.t-dialin.net 208 0.22
19 88.67.165.19=dslb-088-067-165-019.pools.arcor-ip.net 204 0.21
20 91.64.159.105=91-64-159-105-dynip.superkabel.de 196 0.20
21 92.195.85.155=port-92-195-85-155.dynamic.qsc.de 192 0.20
62.242.20.158=cpe.atm2-0-13044.0x3ef2149e.rdnxx6.customer.tele.
22 183 0.19
dk
23 217.88.175.220=pD958AFDC.dip.t-dialin.net 183 0.19
24 194.231.86.195=(not found) 179 0.19
25 24.2.234.252=c-24-2-234-252.hsd1.ct.comcast.net 167 0.17
Sum 96,260 100.00

To top of page

Top 25 of 6012 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 83.160.188.158=atena-2.demon.nl 28,005 2.76
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 17,052 1.68
89.16.140.231=cable-89-16-140-231.cust.blue-cable.
3 16,086 1.59
de
4 70.50.6.234=bas18-toronto12-1177683690.dsl.bell.ca 15,863 1.56
5 82.207.242.19=muedsl-82-207-242-019.citykom.de 12,219 1.20
6 67.195.37.109=llf320031.crawl.yahoo.net 9,615 0.95
7 91.205.124.9=(not found) 9,337 0.92
8 141.244.244.73=iki73.boku.ac.at 7,286 0.72
9 134.28.57.78=pc-r0072-4.w3.tu-harburg.de 7,039 0.69
10 87.79.85.48=xdsl-87-79-85-48.netcologne.de 6,726 0.66
11 84.185.97.126=p54B9617E.dip.t-dialin.net 6,498 0.64
12 87.79.52.147=xdsl-87-79-52-147.netcologne.de 6,440 0.63
13 202.153.240.100=dsl-153.240-100.static.indo.net.id 6,085 0.60
84.61.65.152=dslb-084-061-065-152.pools.arcor-ip.
14 5,750 0.57
net
15 190.161.18.227=(not found) 5,088 0.50
16 87.170.123.83=p57AA7B53.dip.t-dialin.net 5,039 0.50
17 77.12.249.225=mgdb-4d0cf9e1.pool.mediaWays.net 4,813 0.47
18 87.193.252.210=port-87-193-252-210.static.qsc.de 4,734 0.47
19 78.111.65.140=(not found) 4,679 0.46
20 87.189.120.165=p57BD78A5.dip.t-dialin.net 4,519 0.45
21 78.52.113.169=(not found) 4,314 0.43
22 89.110.221.192=pttnet221-192.ptt.rs 4,075 0.40
23 78.1.249.5=78-1-249-5.adsl.net.t-com.hr 3,894 0.38
24 77.180.53.8=koln-4db43508.pool.einsundeins.de 3,842 0.38
25 84.187.225.168=p54BBE1A8.dip.t-dialin.net 3,774 0.37
Sum 1,014,203 100.00

To top of page

Top 25 of 978 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 117 3.36
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 106 3.04
3 88.131.106.16=ca0.entireweb.com 34 0.98
4 193.252.149.15=natcrawlbloc02.net.s1.fti.net 34 0.98
5 81.52.143.15=natcrawlbloc01.net.m1.fti.net 33 0.95
6 66.235.124.3=crawler5003.ask.com 31 0.89
7 81.52.143.26=natcrawlbloc05.net.m1.fti.net 30 0.86
8 81.52.143.16=natcrawlbloc03.net.m1.fti.net 28 0.80
9 212.254.176.2=adsl-176-2-fixip.tiscali.ch 25 0.72
10 74.6.18.228=llf520150.crawl.yahoo.net 18 0.52
11 65.55.212.136=(not found) 18 0.52
12 193.252.149.16=natcrawlbloc04.net.s1.fti.net 18 0.52
65.55.209.168=msnbot-65-55-209-168.search.msn.
13 17 0.49
com
14 85.233.38.20=85.233.38.20.dynamic.cablesurf.de 16 0.46
65.55.209.167=msnbot-65-55-209-167.search.msn.
15 16 0.46
com
65.55.209.153=msnbot-65-55-209-153.search.msn.
16 15 0.43
com
17 91.205.124.9=(not found) 14 0.40
18 74.6.8.125=llf520032.crawl.yahoo.net 14 0.40
19 74.6.17.190=llf520160.crawl.yahoo.net 14 0.40
20 74.6.17.167=llf520193.crawl.yahoo.net 14 0.40
21 24.2.234.252=c-24-2-234-252.hsd1.ct.comcast.net 13 0.37
22 65.55.232.17=(not found) 13 0.37
65.55.209.155=msnbot-65-55-209-155.search.msn.
23 13 0.37
com
24 84.55.114.181=84-55-114-181.customers.ownit.se 12 0.34
25 74.6.22.152=llf520062.crawl.yahoo.net 12 0.34
Sum 3,485 100.00

To top of page

Top 25 of 91 countries of origin , sorted by number of files

N countries of origin times %


1 net 25,287 26.27
2 Germany 21,215 22.04
3 (unresolved) 16,073 16.70
4 com 5,738 5.96
5 Austria 2,499 2.60
6 Poland 2,395 2.49
7 Netherlands 2,048 2.13
8 Switzerland 1,350 1.40
9 Indonesia 1,157 1.20
10 Italy 1,014 1.05
11 Hungary 964 1.00
12 Canada 815 0.85
13 Lithuania 771 0.80
14 Mexico 743 0.77
15 Australia 738 0.77
16 Sweden 717 0.74
17 edu 691 0.72
18 Russian Federation 639 0.66
19 Czech Republic 610 0.63
20 China 604 0.63
21 India 604 0.63
22 Norway 526 0.55
23 Romania 513 0.53
24 Belgium 502 0.52
25 Greece 498 0.52
Sum 96,260 100.00

To top of page

Top 25 of 122 pathes , sorted by number of files

N pathes times %
1 /common/ 32,791 34.07
2 /avr_gra/ 16,841 17.50
3 / 11,451 11.90
4 /avr_en/beginner/ 4,249 4.41
5 /avr_de/beginner/ 3,373 3.50
6 /avr_en/ 3,107 3.23
7 /avr_de/ 2,827 2.94
8 /avr_en/calc/ 2,144 2.23
9 /avr_de/fcount/ 1,515 1.57
10 /avr_de/rechnen/ 1,394 1.45
11 /avr_en/source/ 1,289 1.34
12 /avr_de/stepper/ 1,256 1.30
13 /avr_de/quellen/ 1,102 1.14
14 /avr_de/praesentation/ 1,100 1.14
15 /avr_en/keypad/ 925 0.96
16 /avr_en/signalgen/pics/ 823 0.85
17 /avr_en/stepper/ 734 0.76
18 /avr_de/rechteckgen/bilder/ 714 0.74
19 /gavrasm/ 709 0.74
20 /avr_de/keypad/ 677 0.70
21 /avr_de/zeitschleifen/ 629 0.65
22 /avr_de/interrupts/ 479 0.50
23 /avr_en/signalgen/ 330 0.34
24 /akkuload/ 316 0.33
/avr_de/praesentation/
25 296 0.31
sourcecode/
Sum 96,260 100.00

To top of page

Top 25 of 122 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 177,415 17.49
2 /avr_gra/ 135,559 13.37
3 /avr_de/intro/pdf/ 92,887 9.16
4 / 62,687 6.18
5 /avr_de/fcount/ 58,839 5.80
6 /avr_de/ 43,138 4.25
7 /avr_en/ 42,739 4.21
8 /avr_en/beginner/ 35,891 3.54
9 /avr_de/stepper/ 33,948 3.35
10 /avr_de/beginner/ 32,060 3.16
11 /avr_en/signalgen/pics/ 22,824 2.25
12 /avr_en/calc/ 20,768 2.05
/avr_de/rechteckgen/
13 20,020 1.97
bilder/
14 /gavrasm/v21/ 19,637 1.94
15 /avr_en/stepper/ 19,174 1.89
16 /common/ 15,971 1.57
17 /avr_en/signalgen/ 14,560 1.44
18 /weblox_de/ 13,067 1.29
19 /weblox_en/ 12,427 1.23
20 /avr_de/rechnen/ 12,356 1.22
21 /privat/magloop/ 12,332 1.22
22 /avr_de/intro/ppt/ 11,273 1.11
23 /avr_de/rechteckgen/ 10,422 1.03
24 /akkuload/ 8,163 0.80
25 /avr_en/keypad/ 6,736 0.66
Sum 1,014,203 100.00

To top of page

Top 25 of 1426 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,971 5.16
2 /avr_gra/RingLogo.jpg 2,617 2.72
3 /common/akkuload.gif 2,129 2.21
/common/download.
4 2,127 2.21
gif
5 /common/clock.gif 2,126 2.21
/common/knowhow.
6 2,124 2.21
gif
7 /common/calc.gif 2,121 2.20
8 /avr_gra/stk_lcd.jpg 2,119 2.20
9 /common/gavrasm.gif 2,119 2.20
10 /common/app.gif 2,118 2.20
/common/gavrasmw.
11 2,114 2.20
gif
12 /common/example.gif 2,113 2.20
13 /common/keyb.gif 2,112 2.19
14 /common/beginner.gif 2,110 2.19
15 /common/adc.gif 2,110 2.19
16 /common/r2r.gif 2,106 2.19
17 /common/hardware.gif 2,105 2.19
18 /index.html 1,505 1.56
19 /avr_en/index.html 1,327 1.38
20 /avr_2313.gif 1,264 1.31
21 /dg4fac.gif 1,204 1.25
22 /avr-asm-tutorial.gif 1,198 1.24
23 /avr_de/index.html 1,186 1.23
24 /avr_gra/2313.gif 1,143 1.19
25 /common/ints.gif 1,051 1.09
Sum 96,260 100.00

To top of page

Top 25 of 1426 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 56,476 5.57
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 35,176 3.47
3 /avr_de/index.html 27,217 2.68
4 /avr_en/index.html 27,146 2.68
5 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 25,276 2.49
6 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 21,423 2.11
7 /avr_2313.gif 21,364 2.11
/avr_de/praesentation/Teil_5b_Beispiel01_02.
8 21,059 2.08
pdf
9 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 16,114 1.59
10 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 15,641 1.54
11 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 15,052 1.48
12 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 14,619 1.44
13 /dg4fac.gif 12,784 1.26
14 /avr_gra/pwm_simul.jpg 11,629 1.15
15 /avr_de/fcount/dscf0004.jpg 11,419 1.13
16 /avr_de/intro/pdf/Teil1_Prozessor.pdf 11,098 1.09
17 /avr_gra/r2r_hardware.jpg 11,004 1.08
18 /avr_en/signalgen/pics/rectgen_wiring.jpg 10,516 1.04
19 /avr_de/fcount/dscf0005.jpg 9,792 0.97
20 /favicon.ico 9,772 0.96
21 /avr_de/fcount/dscf0001.jpg 9,252 0.91
22 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 9,221 0.91
23 /avr_gra/2313.gif 8,504 0.84
24 /avr_de/stepper/stepper_v1.gif 8,355 0.82
25 /avr_gra/exp2313.gif 8,272 0.82
Sum 1,014,203 100.00

To top of page

Top 25 of 434 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,505 6.96
2 /avr_en/index.html 1,327 6.14
3 /avr_de/index.html 1,186 5.48
4 /avr_en/beginner/index.html 781 3.61
5 /avr_en/beginner/RIGHT.html 750 3.47
6 /avr_en/beginner/LEFT.html 741 3.43
7 /avr_de/beginner/index.html 518 2.40
8 /avr_de/beginner/links.html 500 2.31
9 /avr_de/beginner/rechts.html 481 2.22
/avr_en/beginner/HARDWARE.
10 251 1.16
html
11 /avr_en/beginner/REGISTER.html 229 1.06
12 /avr_en/AVR_DAC.html 220 1.02
13 /avr_de/beginner/hardware.html 219 1.01
14 /avr_en/beginner/JUMP.html 202 0.93
15 /avr_de/beginner/register.html 192 0.89
16 /avr_en/keypad/keyboard.html 186 0.86
17 /avr_de/beginner/werkzeuge.html 180 0.83
18 /avr_de/stepper/stepper.html 178 0.82
19 /avr_de/praesentation/index.html 176 0.81
20 /avr_en/beginner/TOOLS.html 172 0.80
21 /avr_en/AVR_TUT.html 165 0.76
22 /avr_de/apps.html 165 0.76
23 /avr_de/beginner/sprung.html 163 0.75
24 /avr_en/beginner/PORTS.html 150 0.69
25 /avr_de/zeitschleifen/index.html 150 0.69
Sum 21,628 100.00

To top of page

Top 25 of 434 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 27,217 10.79
2 /avr_en/index.html 27,146 10.76
3 /index.html 7,997 3.17
4 /avr_en/beginner/RIGHT.html 5,488 2.17
5 /avr_en/beginner/JUMP.html 4,758 1.89
6 /avr_de/beginner/sprung.html 4,588 1.82
7 /gb_new.html 4,132 1.64
8 /avr_en/keypad/keyboard.html 3,784 1.50
9 /avr_en/beginner/CALC.html 3,692 1.46
10 /avr_de/dcf77uhr.html 3,564 1.41
11 /avr_de/beginner/rechts.html 3,488 1.38
12 /avr_de/beginner/rechnen.html 3,483 1.38
13 /avr_en/beginner/LEFT.html 3,445 1.37
14 /avr_en/AVR_DAC.html 3,184 1.26
15 /avr_de/keypad/keyboard.html 2,992 1.19
16 /avr_en/signalgen/rectgen_m8.html 2,910 1.15
/avr_en/beginner/COMMANDS.
17 2,772 1.10
html
18 /avr_de/stepper/stepper.html 2,736 1.08
19 /avr_en/beginner/REGISTER.html 2,717 1.08
20 /avr_en/beginner/PDETAIL.html 2,660 1.05
21 /avr_de/fcount/fcount_m8_v2.html 2,646 1.05
/avr_de/rechteckgen/rectgen_m8.
22 2,640 1.05
html
23 /avr_de/beginner/pdetail.html 2,632 1.04
24 /avr_de/beginner/commands.html 2,618 1.04
25 /avr_de/beginner/links.html 2,335 0.93
Sum 252,347 100.00

To top of page

Top 25 of 368 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,614 18.72
2 /avr_gra/stk_lcd.jpg 2,118 15.17
3 /avr_gra/8515.jpg 535 3.83
4 /avr_gra/exp2313g.jpg 454 3.25
5 /avr_gra/avr_isp.jpg 438 3.14
6 /avr_gra/exp_2313.jpg 421 3.02
7 /avr_gra/r2r_wave.jpg 336 2.41
8 /avr_gra/r2r_sawtooth.jpg 327 2.34
9 /avr_gra/r2r_hardware.jpg 316 2.26
10 /avr_gra/r2r_triangle.jpg 312 2.23
11 /avr_gra/r2r_sawtoothupperbound.jpg 311 2.23
12 /avr_gra/r2r_sawtooth741.jpg 311 2.23
13 /avr_gra/r2r_upperbound.jpg 308 2.21
14 /avr_gra/AT90S8515.jpg 261 1.87
15 /avr_gra/adc8conn.jpg 210 1.50
16 /avr_gra/pwm_simul.jpg 208 1.49
17 /avr_gra/apps.jpg 208 1.49
18 /avr_en/signalgen/pics/rectgen_280.jpg 176 1.26
19 /avr_de/stepper/stepper_sm.jpg 175 1.25
20 /avr_de/stepper/kp4m4-001.jpg 163 1.17
21 /avr_de/stepper/driver.jpg 161 1.15
22 /avr_de/stepper/supply.jpg 161 1.15
23 /avr_de/praesentation/zuendtester.jpg 153 1.10
/avr_de/rechteckgen/bilder/rectgen_280.
24 149 1.07
jpg
25 /akkuload/dscf0030s.jpg 149 1.07
Sum 13,962 100.00

To top of page

Top 25 of 335 GIF-files , sorted by number of files

N GIF-files times %
1 /common/akkuload.gif 2,129 4.28
/common/download.
2 2,124 4.27
gif
3 /common/clock.gif 2,124 4.27
/common/knowhow.
4 2,122 4.26
gif
5 /common/calc.gif 2,119 4.26
6 /common/gavrasm.gif 2,117 4.25
7 /common/app.gif 2,116 4.25
/common/gavrasmw.
8 2,112 4.24
gif
9 /common/beginner.gif 2,110 4.24
10 /common/keyb.gif 2,110 4.24
11 /common/example.gif 2,109 4.24
12 /common/adc.gif 2,108 4.23
13 /common/r2r.gif 2,106 4.23
14 /common/hardware.gif 2,105 4.23
15 /avr_2313.gif 1,264 2.54
16 /dg4fac.gif 1,204 2.42
17 /avr-asm-tutorial.gif 1,198 2.41
18 /avr_gra/2313.gif 1,143 2.30
19 /common/ints.gif 1,051 2.11
20 /common/tn13.gif 1,051 2.11
21 /common/delay.gif 1,051 2.11
22 /avr_gra/exp2313.gif 475 0.95
23 /avr_gra/avr_isp.gif 428 0.86
24 /avr_gra/screenshot.gif 425 0.85
25 /avr_gra/isp6pin.gif 421 0.85
Sum 49,778 100.00

To top of page

Top 25 of 180 entry pages , sorted by number of files

N entry pages times %


1 /index.html 757 16.04
2 /avr_en/index.html 518 10.98
3 /avr_de/index.html 376 7.97
4 /avr_en/beginner/index.html 296 6.27
5 /avr_de/beginner/index.html 147 3.12
6 /avr_en/AVR_DAC.html 131 2.78
7 /avr_de/stepper/stepper.html 98 2.08
8 /avr_de/avr_dac.html 84 1.78
9 /avr_en/signalgen/rectgen_m8.html 81 1.72
10 /avr_en/beginner/HARDWARE.html 76 1.61
11 /avr_de/fcount/fcount_m8.html 72 1.53
12 /avr_en/keypad/keyboard.html 67 1.42
/avr_de/rechteckgen/rectgen_m8.
13 63 1.34
html
14 /avr_en/AVR_ADC500.html 62 1.31
15 /avr_de/keypad/keyboard.html 56 1.19
16 /avr_de/intro/index.html 53 1.12
17 /avr_en/stepper/stepper.html 49 1.04
18 /avr_de/rechnen/multiplikation.html 47 1.00
19 /avr_de/rechnen/konversion.html 47 1.00
20 /avr_de/beginner/hardware.html 42 0.89
21 /avr_de/beginner/rechnen.html 40 0.85
22 /gb_new.html 39 0.83
23 /avr_de/avr_adc500.html 37 0.78
24 /avr_de/beginner/diraus.html 37 0.78
25 /avr_de/beginner/pdetail.html 34 0.72
Sum 4,719 100.00

To top of page

Top 25 of 217 cheat pages , sorted by number of files

N cheat pages times %


1 805 13.39
2 /index.html 476 7.92
3 /avr_en/index.html 409 6.80
4 /avr_de/index.html 341 5.67
5 /avr_en/beginner/RIGHT.html 196 3.26
6 /avr_en/AVR_DAC.html 147 2.45
7 /avr_en/beginner/HARDWARE.html 106 1.76
8 /avr_en/keypad/keyboard.html 101 1.68
9 /avr_de/beginner/rechts.html 100 1.66
10 /avr_de/stepper/stepper.html 96 1.60
11 /avr_de/avr_dac.html 79 1.31
12 /avr_de/keypad/keyboard.html 78 1.30
13 /avr_de/fcount/fcount_m8.html 75 1.25
14 /avr_en/beginner/REGISTER.html 72 1.20
15 /avr_en/signalgen/rectgen_m8.html 70 1.16
16 /avr_en/AVR_ADC500.html 63 1.05
17 /avr_de/beginner/hardware.html 59 0.98
18 /avr_en/beginner/JUMP.html 59 0.98
19 /avr_de/beginner/rechnen.html 58 0.96
/avr_de/rechteckgen/rectgen_m8.
20 57 0.95
html
21 /avr_de/praesentation/index.html 55 0.91
22 /avr_en/stepper/stepper.html 53 0.88
23 /avr_de/rechnen/multiplikation.html 52 0.86
24 /avr_de/beginner/werkzeuge.html 52 0.86
25 /avr_de/intro/index.html 45 0.75
Sum 6,012 100.00

To top of page

Top 25 of 170 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,539 14.26
2 /avr_en/beginner/index.html 1,324 12.26
3 / 900 8.34
4 /avr_de/beginner/index.html 839 7.77
5 /avr_en/index.html 676 6.26
6 /avr_en/ 579 5.36
7 /avr_en/beginner/RIGHT.html 538 4.98
8 /avr_de/beginner/rechts.html 525 4.86
9 /avr_en/beginner/LEFT.html 440 4.08
10 /avr_de/beginner/links.html 341 3.16
11 /avr_de/ 210 1.95
12 /sitemap_de.html 172 1.59
13 /avr_de/apps.html 157 1.45
14 /sitemap_en.html 135 1.25
15 /avr_en/AVR_TUT.html 133 1.23
16 /avr_en/calc/index.html 132 1.22
17 /weblox_en/index.html 132 1.22
18 /avr_de/interrupts/index.html 131 1.21
19 /avr_de/zeitschleifen/index.html 130 1.20
20 /index.html 128 1.19
21 /avr_de/avr_tut.html 99 0.92
22 /weblox_de/ 68 0.63
23 /avr_en/APPS.html 68 0.63
24 /weblox_de/index.html 68 0.63
/avr_de/beginner/commands.
25 65 0.60
html
Sum 10,795 100.00

To top of page

Top 25 of 414 external referrers , sorted by number of files

N external referrers times %


1 - 5,936 84.08
2 http://www.mikrocontroller.net/articles/AVR 49 0.69
3 http://www.webring.com/hub?ring=avr 29 0.41
4 http://www.dg4fac.de/stechlin/ 24 0.34
5 http://www.educypedia.be/electronics/avr.htm 23 0.33
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
6 23 0.33
ESC_by1_bz0_bs0.html
7 http://avr-asm.tripod.com/ 22 0.31
8 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 22 0.31
9 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 18 0.25
10 http://www.rowalt.de/mc/avr/linksd.htm 18 0.25
11 http://de.wikipedia.org/wiki/R2R-Netzwerk 17 0.24
12 http://politecnica.cv.uma.es/mod/resource/view.php?id=13449 16 0.23
13 http://www.dg4fac.de/linksunten.html 16 0.23
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
14 15 0.21
kurs.htm
15 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment 15 0.21
16 http://www.edw.com.pl/ea/asm_avr_jezyk.html 14 0.20
17 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 14 0.20
http://www.avrfreaks.net/index.php?
18 name=PNphpBB2&file=viewtopic&t=7067 13 0.18
3
19 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 13 0.18
20 http://www.mikrocontroller.net/articles/Linksammlung 12 0.17
21 http://www.dg4fac.de/rechtsunten.html 12 0.17
22 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 11 0.16
23 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 10 0.14
http://electrons.psychogenic.com/modules/arms/art/3/
24 AVRGCCProgrammingG 10 0.14
uide.php
http://www.avrfreaks.net/index.php?module=Freaks%
25 20Academy&func=viewIt 9 0.13
em&item_id=355&item_type=project
Sum 7,060 100.00

To top of page

Top 25 of 126 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,472 41.49
2 http://www.google.com 672 18.94
3 http://www.google.at 109 3.07
http://www.stumbleupon.
4 77 2.17
com
5 http://www.google.pl 74 2.09
6 http://www.google.co.in 71 2.00
7 http://www.google.co.uk 70 1.97
8 http://www.google.ch 69 1.94
9 http://www.google.nl 58 1.63
10 http://www.google.ca 39 1.10
11 http://www.google.com.au 34 0.96
12 http://www.google.se 34 0.96
13 http://www.google.co.id 33 0.93
14 http://www.google.fi 29 0.82
15 http://www.google.ro 27 0.76
16 http://www.google.hu 25 0.70
17 http://www.google.cz 25 0.70
18 http://www.google.gr 24 0.68
19 http://www.google.com.br 22 0.62
20 http://www.google.hr 22 0.62
21 http://www.google.ru 21 0.59
22 http://de.search.yahoo.com 21 0.59
23 http://www.google.pt 20 0.56
24 http://search.live.com 20 0.56
25 http://www.google.fr 20 0.56
Sum 3,548 100.00

To top of page

Top 25 of 2345 search strings , sorted by number of files

N search strings times %


1 avr tutorial 89 2.51
http://www.avr-asm-tutorial.net/avr_en/beginner/index.
2 77 2.17
html
3 avr assembler 53 1.49
4 avr 43 1.21
5 attiny13 38 1.07
6 avr programming 34 0.96
7 assembler 33 0.93
8 assembler tutorial 30 0.85
9 avr assembly 26 0.73
10 avr asm 23 0.65
11 avr assembler tutorial 17 0.48
12 stk500 12 0.34
13 atmega8 12 0.34
14 MCUCR 12 0.34
15 ATtiny13 12 0.34
16 AVR MCU courseware 12 0.34
17 AVR 11 0.31
18 wavrasm 11 0.31
19 assembler avr 11 0.31
20 assembler commands 10 0.28
21 AVR assembler 10 0.28
22 avr tutorials 10 0.28
23 mcucr 9 0.25
24 asm tutorial 9 0.25
25 r2r 9 0.25
Sum 3,548 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 87,263 90.65
2 304 Not changed 7,939 8.25
3 206 Partial information 429 0.45
4 404 File not found 352 0.37

http://www.avr-asm-tutorial.net/weblox_en/2008w45.html (1 of 2)1/20/2009 8:10:26 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 301 Permanently moved 185 0.19


6 403 Forbidden 81 0.08
7 300 Multiple choices 5 0.01
8 xxx Unknown error 5 0.01
9 405 Method not allowed 1 0.00
Sum 96,260 100.00

To top of page

Top 25 of 59 files not found , sorted by number of files

N files not found times %


1 /_vpi.xml 156 44.32
2 /avr_en/source/_vpi.xml 43 12.22
3 /beginner_en.pdf 35 9.94
4 /beginner_de.pdf 27 7.67
5 /_vti_inf.html 10 2.84
/_vti_bin/owssvr.dll?
6 7 1.99
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
7 7 1.99
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/modules/3rdparty/adminpart/add3rdparty.php?module=http://geeklinuxer.
8 4 1.14
co.cc/data/Gang11/id?
9 /avr_en/_vpi.xml 3 0.85
/_vti_bin/owssvr.dll?
10 3 0.85
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
11 3 0.85
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
12 /sitemap.xml 2 0.57
13 /common/example.gif 2 0.57
/avr_en/beginner/%D0%94%D0%BB%D1%8F%20%D0%BD%D0%B0%
D1%87%D0%B8%D0%BD%D
0%B0%D1%8E%D1%89%D0%B8%D1%85%20%D0%B2%D0%BD%
14 D0%B5%D0%B4%D1%80%D0%B5%D0 2 0.57
%BD%D0%B8%D0%B5%20AVR%20%D0%BD%D0%B0%20%D1%8F
%D0%B7%D1%8B%D0%BA%D0%B5%
20%D0%B0%D1%81%D1%81%D0%B5%D0%BC%D0%B1%D0
//components/com_simpleboard/file_upload.php?sbp=http://125.250.78.194
15 2 0.57
/rgboard/manual/.../sistem.txt???
/avr_de/beginner/diraus.html/modules/3rdparty/adminpart/add3rdparty.ph
16 2 0.57
p?module=http://geeklinuxer.co.cc/data/Gang11/id?
/avr_de/beginner/modules/3rdparty/adminpart/add3rdparty.php?module=htt
17 2 0.57
p://geeklinuxer.co.cc/data/Gang11/id?
18 /avr_en/stepper/schrittmotor_v1.html 1 0.28
19 /avr_en/quellen/schrittmotor_v1.asm 1 0.28
20 /avr_gra/r2r_sine.jpg 1 0.28
/_vti_bin/owssvr.dll?
21 1 0.28
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
22 1 0.28
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
23 /avr_en/beginner/2313.gif 1 0.28
24 /avr_en/beginner/DIREXP.html 1 0.28
25 /favicon.ico 1 0.28
Sum 352 100.00

To top of page

Top 25 of 114 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 51,783 53.79
2 Mozilla/4.0 33,334 34.63
3 Opera/9.62 1,403 1.46
4 Mozilla/4.5 956 0.99
5 Yanga 910 0.95
6 Anonymous 741 0.77
7 Opera/9.60 707 0.73
8 Opera/9.25 693 0.72
9 - 576 0.60
10 Opera/9.52 516 0.54
11 Opera/9.61 379 0.39
12 Opera/9.51 370 0.38
13 Opera/9.27 335 0.35
14 Opera/9.26 317 0.33
15 msnbot/1.1 310 0.32
16 Opera/9.50 287 0.30
17 Eurobot/1.0 245 0.25
18 Yandex/1.01.001 234 0.24
19 Googlebot-Image/1.0 229 0.24
20 yacybot 215 0.22
21 Firebat 202 0.21
22 msnbot-media/1.1 174 0.18
23 Windows XP 136 0.14
ia_archiver-web.archive.
24 111 0.12
org
25 Opera/9.24 99 0.10
Sum 96,260 100.00

To top of page

Top 25 of 247 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.3 29,666 30.82
2 MSIE 7.0 16,028 16.65
3 MSIE 6.0 14,634 15.20
4 Firefox/2.0.0.17 5,168 5.37
5 unknown 3,027 3.14
6 Firefox/3.0.1 2,103 2.18
7 Gecko 1,850 1.92
8 Firefox/3.0.3 1,564 1.62
9 Opera/9.62 1,403 1.46
10 Slurp 1,367 1.42
11 Firefox/3.0 1,210 1.26
12 HTTrack 3.0x 956 0.99
13 FDM 845 0.88
14 Opera/9.60 707 0.73
15 Googlebot/2.1 696 0.72
16 Opera/9.25 525 0.55
17 Opera/9.52 516 0.54
18 Firefox/2.0.0.14 487 0.51
Gecko/2008092816
19 434 0.45
Iceweasel/3.0.3
20 Opera/9.61 379 0.39
21 MSIE 5.5 371 0.39
22 Firefox/2.0 371 0.39
23 Opera/9.51 370 0.38
24 Firefox/3.0.2 370 0.38
25 Opera/9.27 335 0.35
Sum 96,260 100.00

To top of page

Top 25 of 45 operating systems , sorted by number of files

N operating systems times %


1 Windows 41,241 42.84
2 Windows NT 5.1 28,689 29.80
3 unknown 7,659 7.96
4 Linux i686 5,254 5.46
5 Windows NT 6.0 4,729 4.91
6 Windows NT 5.0 2,882 2.99
7 Windows 98 1,580 1.64
8 Linux x86_64 1,075 1.12
9 Mac OS X 10_5_5 552 0.57
10 Mac OS X 10.5 429 0.45
11 Linux 335 0.35
12 Win16 234 0.24
13 Windows NT 5.2 201 0.21
14 Mac OS X 10_4_11 184 0.19
15 Windows XP 136 0.14
16 Linux i686 130 0.14
17 Mac OS X 10.4 128 0.13
18 Windows XP 5.1 99 0.10
19 Linux 2.6.27-7-generic 98 0.10
20 Mac OS X 80 0.08
21 Mac OS X Mach-O 77 0.08
22 Windows NT 4.0 74 0.08
23 Windows ME 74 0.08
Linux 2.6.25.9-0.2-
24 55 0.06
default
25 Windows 6.0 51 0.05
Sum 96,260 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,410 2.50
2 01 1,892 1.97
3 02 1,536 1.60
4 03 1,614 1.68
5 04 1,610 1.67
6 05 2,226 2.31
7 06 1,653 1.72
8 07 1,840 1.91
9 08 3,268 3.39
10 09 4,039 4.20
11 10 4,026 4.18
12 11 4,802 4.99
13 12 5,194 5.40
14 13 4,716 4.90
15 14 6,011 6.24
16 15 6,231 6.47
17 16 6,185 6.43
18 17 5,115 5.31
19 18 6,527 6.78
20 19 5,758 5.98
21 20 4,918 5.11
22 21 5,070 5.27
23 22 5,191 5.39
24 23 4,428 4.60
Sum 96,260 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w45.html (2 of 2)1/20/2009 8:10:26 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w44

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 44

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5748 IPs and host names , sorted by number of files

N IPs and host names times %


1 213.192.2.142=tlapnet.cust.sloane.cz 1,448 1.55
2 67.195.37.109=llf320031.crawl.yahoo.net 666 0.71
3 149.217.1.6=www-cache2.mpi-hd.mpg.de 621 0.67
4 89.61.245.32=Zf520.z.pppool.de 532 0.57
5 66.249.72.79=crawl-66-249-72-79.googlebot.com 493 0.53
6 91.124.107.175=175-107-124-91.pool.ukrtel.net 376 0.40
7 201.13.157.186=201-13-157-186.dial-up.telesp.net.br 369 0.40
8 83.228.78.216=(not found) 362 0.39
9 91.205.124.9=(not found) 351 0.38
10 202.87.191.134=(not found) 346 0.37
11 193.23.168.169=inflab.et.fh-duesseldorf.de 335 0.36
12 78.162.190.144=(not found) 298 0.32
13 87.174.75.109=p57AE4B6D.dip.t-dialin.net 291 0.31
14 92.195.242.126=port-92-195-242-126.dynamic.qsc.de 272 0.29
15 80.121.62.50=80-121-62-50.adsl.highway.telekom.at 264 0.28
16 88.73.37.251=dslb-088-073-037-251.pools.arcor-ip.net 257 0.28
17 78.46.78.40=crawlh004.ayell.org 245 0.26
66.191.238.136=66-191-238-136.dhcp.kgpt.tn.charter.
18 244 0.26
com
19 83.236.164.131=port-83-236-164-131.static.qsc.de 238 0.26
20 85.181.109.18=e181109018.adsl.alicedsl.de 207 0.22
21 195.80.166.34=tnet.psg.sk 195 0.21
22 91.129.7.53=d91-129-7-53.cust.tele2.at 191 0.20
23 218.28.247.131=pc0.zz.ha.cn 189 0.20
24 66.235.124.3=crawler5003.ask.com 187 0.20
25 85.158.227.32=(not found) 184 0.20
Sum 93,193 100.00

To top of page

Top 25 of 5748 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 149.217.1.6=www-cache2.mpi-hd.mpg.de 15,832 1.67
2 77.22.123.118=(not found) 13,986 1.47
3 84.140.65.19=p548C4113.dip0.t-ipconnect.de 12,956 1.36
4 67.195.37.109=llf320031.crawl.yahoo.net 11,830 1.24
5 141.6.8.89=(not found) 11,326 1.19
6 91.124.107.175=175-107-124-91.pool.ukrtel.net 7,350 0.77
7 85.127.95.156=85-127-95-156.dynamic.xdsl-line.inode.at 6,565 0.69
8 193.23.168.169=inflab.et.fh-duesseldorf.de 5,705 0.60
9 91.34.233.152=p5B22E998.dip.t-dialin.net 5,590 0.59
10 213.192.2.142=tlapnet.cust.sloane.cz 5,376 0.57
11 87.174.75.109=p57AE4B6D.dip.t-dialin.net 5,261 0.55
12 84.183.241.184=p54B7F1B8.dip.t-dialin.net 4,990 0.52
13 79.193.79.140=p4FC14F8C.dip.t-dialin.net 4,503 0.47
14 87.123.203.88=i577BCB58.versanet.de 4,373 0.46
15 89.61.245.32=Zf520.z.pppool.de 4,362 0.46
16 92.195.97.14=port-92-195-97-14.dynamic.qsc.de 4,275 0.45
17 91.47.196.106=p5B2FC46A.dip.t-dialin.net 4,217 0.44
18 79.218.236.44=p4FDAEC2C.dip.t-dialin.net 4,180 0.44
19 202.87.191.134=(not found) 4,133 0.43
20 66.249.72.79=crawl-66-249-72-79.googlebot.com 3,803 0.40
21 91.3.35.172=p5B0323AC.dip0.t-ipconnect.de 3,763 0.40
22 87.234.194.10=port-87-234-194-10.static.qsc.de 3,712 0.39
23 38.105.83.13=(not found) 3,597 0.38
24 91.205.124.9=(not found) 3,566 0.38
91.89.16.12=HSI-KBW-091-089-016-012.hsi2.kabelbw.
25 3,426 0.36
de
Sum 950,788 100.00

To top of page

Top 25 of 959 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 110 2.97
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 88 2.38
3 66.235.124.3=crawler5003.ask.com 86 2.32
4 208.111.154.16=crawl2.nat.svl.searchme.com 62 1.67
5 208.111.154.15=crawl1.nat.svl.searchme.com 51 1.38
6 88.131.106.16=ca0.entireweb.com 27 0.73
7 212.254.176.2=adsl-176-2-fixip.tiscali.ch 24 0.65
65.55.209.167=msnbot-65-55-209-167.search.msn.
8 22 0.59
com
65.55.209.165=msnbot-65-55-209-165.search.msn.
9 22 0.59
com
65.55.209.152=msnbot-65-55-209-152.search.msn.
10 22 0.59
com
11 81.52.143.16=natcrawlbloc03.net.m1.fti.net 21 0.57
12 193.252.149.15=natcrawlbloc02.net.s1.fti.net 21 0.57
65.55.209.153=msnbot-65-55-209-153.search.msn.
13 21 0.57
com
14 81.52.143.26=natcrawlbloc05.net.m1.fti.net 20 0.54
65.55.209.151=msnbot-65-55-209-151.search.msn.
15 19 0.51
com
65.55.209.169=msnbot-65-55-209-169.search.msn.
16 17 0.46
com
65.55.209.154=msnbot-65-55-209-154.search.msn.
17 16 0.43
com
65.55.209.159=msnbot-65-55-209-159.search.msn.
18 16 0.43
com
19 91.205.124.9=(not found) 15 0.41
20 81.52.143.15=natcrawlbloc01.net.m1.fti.net 15 0.41
21 193.47.80.44=crawl8.exabot.com 15 0.41
65.55.209.164=msnbot-65-55-209-164.search.msn.
22 15 0.41
com
65.55.209.158=msnbot-65-55-209-158.search.msn.
23 15 0.41
com
24 77.22.18.102=(not found) 14 0.38
65.55.209.166=msnbot-65-55-209-166.search.msn.
25 14 0.38
com
Sum 3,703 100.00

To top of page

Top 25 of 98 countries of origin , sorted by number of files

N countries of origin times %


1 net 24,557 26.35
2 Germany 21,113 22.66
3 (unresolved) 16,445 17.65
4 com 5,968 6.40
5 Austria 2,928 3.14
6 Poland 2,764 2.97
7 Czech Republic 1,705 1.83
8 Netherlands 1,364 1.46
9 Italy 1,127 1.21
10 Switzerland 1,065 1.14
11 Belgium 943 1.01
12 Mexico 809 0.87
13 Brazil 803 0.86
14 Australia 745 0.80
15 Hungary 714 0.77
16 Lithuania 638 0.68
17 Sweden 604 0.65
18 Slovak Republic 602 0.65
19 India 594 0.64
20 edu 589 0.63
21 United Kingdom 405 0.43
22 Canada 395 0.42
23 Indonesia 341 0.37
24 org 334 0.36
25 Russian Federation 331 0.36
Sum 93,193 100.00

To top of page

Top 25 of 108 pathes , sorted by number of files

N pathes times %
1 /common/ 32,413 34.78
2 /avr_gra/ 16,377 17.57
3 / 11,547 12.39
4 /avr_en/beginner/ 4,629 4.97
5 /avr_de/beginner/ 3,133 3.36
6 /avr_en/ 2,896 3.11
7 /avr_de/ 2,687 2.88
8 /avr_en/calc/ 1,743 1.87
9 /avr_de/fcount/ 1,699 1.82
10 /avr_de/stepper/ 1,195 1.28
11 /avr_en/source/ 1,185 1.27
12 /avr_de/rechnen/ 1,149 1.23
13 /avr_de/praesentation/ 1,023 1.10
14 /avr_en/keypad/ 994 1.07
15 /avr_de/quellen/ 840 0.90
16 /avr_en/signalgen/pics/ 809 0.87
17 /avr_en/stepper/ 731 0.78
18 /avr_de/interrupts/ 728 0.78
19 /gavrasm/ 720 0.77
20 /avr_de/keypad/ 663 0.71
21 /avr_de/rechteckgen/bilder/ 549 0.59
22 /avr_de/zeitschleifen/ 505 0.54
23 /akkuload/ 376 0.40
24 /avr_en/signalgen/ 330 0.35
/avr_de/praesentation/
25 292 0.31
sourcecode/
Sum 93,193 100.00

To top of page

Top 25 of 108 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 180,874 19.02
2 /avr_gra/ 129,989 13.67
3 /avr_de/intro/pdf/ 84,207 8.86
4 /avr_de/fcount/ 68,041 7.16
5 / 64,999 6.84
6 /avr_de/ 42,144 4.43
7 /avr_en/ 39,915 4.20
8 /avr_en/beginner/ 34,099 3.59
9 /avr_de/stepper/ 32,136 3.38
10 /avr_de/beginner/ 27,045 2.84
11 /avr_en/signalgen/pics/ 21,408 2.25
12 /avr_en/stepper/ 18,758 1.97
13 /gavrasm/v21/ 16,536 1.74
14 /avr_en/calc/ 15,746 1.66
15 /common/ 15,352 1.61
/avr_de/rechteckgen/
16 15,059 1.58
bilder/
17 /avr_en/signalgen/ 11,943 1.26
18 /avr_de/rechnen/ 10,214 1.07
19 /avr_de/interrupts/ 9,791 1.03
20 /akkuload/ 8,807 0.93
21 /avr_de/intro/ppt/ 8,530 0.90
22 /avr_de/rechteckgen/ 8,485 0.89
23 /privat/magloop/ 7,480 0.79
24 /avr_en/keypad/ 7,199 0.76
25 /weblox_en/ 6,268 0.66
Sum 950,788 100.00

To top of page

Top 25 of 1211 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,723 5.07
2 /avr_gra/RingLogo.jpg 2,655 2.85
3 /common/clock.gif 2,101 2.25
/common/knowhow.
4 2,099 2.25
gif
5 /common/app.gif 2,099 2.25
6 /common/akkuload.gif 2,097 2.25
7 /common/example.gif 2,096 2.25
/common/download.
8 2,096 2.25
gif
9 /common/gavrasm.gif 2,095 2.25
10 /common/calc.gif 2,092 2.24
/common/gavrasmw.
11 2,088 2.24
gif
12 /common/beginner.gif 2,087 2.24
13 /avr_gra/stk_lcd.jpg 2,086 2.24
14 /common/keyb.gif 2,086 2.24
15 /common/r2r.gif 2,081 2.23
16 /common/adc.gif 2,079 2.23
17 /common/hardware.gif 2,078 2.23
18 /index.html 1,663 1.78
19 /avr_2313.gif 1,411 1.51
20 /dg4fac.gif 1,295 1.39
21 /avr-asm-tutorial.gif 1,290 1.38
22 /avr_en/index.html 1,266 1.36
23 /avr_de/index.html 1,170 1.26
24 /avr_gra/2313.gif 1,060 1.14
25 /common/ints.gif 1,049 1.13
Sum 93,193 100.00

To top of page

Top 25 of 1211 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 68,122 7.16
2 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 35,856 3.77
3 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 32,847 3.45
4 /avr_de/index.html 26,108 2.75
5 /avr_en/index.html 25,465 2.68
6 /avr_2313.gif 22,373 2.35
7 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 19,022 2.00
/avr_de/praesentation/Teil_5b_Beispiel01_02.
8 17,354 1.83
pdf
9 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 16,613 1.75
10 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 15,052 1.58
11 /avr_de/fcount/dscf0004.jpg 13,580 1.43
12 /dg4fac.gif 13,378 1.41
13 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 12,203 1.28
14 /avr_de/fcount/dscf0005.jpg 11,928 1.25
15 /avr_gra/pwm_simul.jpg 11,602 1.22
16 /avr_de/fcount/dscf0001.jpg 11,095 1.17
17 /avr_gra/r2r_hardware.jpg 10,558 1.11
18 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 10,459 1.10
19 /avr_en/signalgen/pics/rectgen_wiring.jpg 9,762 1.03
20 /favicon.ico 9,289 0.98
21 /index.html 8,714 0.92
22 /avr_de/fcount/fcount.jpg 8,540 0.90
23 /avr_gra/exp2313.gif 7,999 0.84
24 /avr_de/stepper/stepper_v1.gif 7,897 0.83
25 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 7,838 0.82
Sum 950,788 100.00

To top of page

Top 25 of 410 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,663 7.97
2 /avr_en/index.html 1,266 6.07
3 /avr_de/index.html 1,170 5.61
4 /avr_en/beginner/index.html 964 4.62
5 /avr_en/beginner/LEFT.html 935 4.48
6 /avr_en/beginner/RIGHT.html 685 3.28
7 /avr_de/beginner/index.html 509 2.44
8 /avr_de/beginner/links.html 503 2.41
9 /avr_de/beginner/rechts.html 434 2.08
/avr_en/beginner/HARDWARE.
10 272 1.30
html
11 /avr_en/beginner/WHY.html 262 1.26
12 /avr_en/beginner/REGISTER.html 216 1.04
13 /avr_en/keypad/keyboard.html 207 0.99
14 /avr_en/AVR_DAC.html 180 0.86
15 /avr_en/beginner/JUMP.html 178 0.85
16 /avr_de/beginner/hardware.html 177 0.85
17 /avr_de/beginner/register.html 174 0.83
18 /avr_de/stepper/stepper.html 169 0.81
19 /avr_de/praesentation/index.html 166 0.80
20 /avr_de/beginner/werkzeuge.html 165 0.79
21 /avr_en/beginner/TOOLS.html 165 0.79
22 /avr_de/apps.html 164 0.79
23 /avr_de/fcount/fcount_m8.html 161 0.77
24 /avr_en/AVR_ADC500.html 158 0.76
25 /avr_en/beginner/PORTS.html 157 0.75
Sum 20,857 100.00

To top of page

Top 25 of 410 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_de/index.html 26,108 11.79
2 /avr_en/index.html 25,465 11.50
3 /index.html 8,714 3.93
4 /avr_en/beginner/RIGHT.html 4,640 2.09
5 /avr_de/dcf77uhr.html 4,374 1.97
6 /gb_new.html 4,360 1.97
7 /avr_en/beginner/JUMP.html 4,342 1.96
8 /avr_en/keypad/keyboard.html 4,110 1.86
9 /avr_en/beginner/CALC.html 3,666 1.66
10 /avr_de/beginner/sprung.html 3,410 1.54
11 /avr_de/beginner/rechts.html 3,064 1.38
12 /avr_de/keypad/keyboard.html 3,036 1.37
13 /avr_en/beginner/LEFT.html 2,920 1.32
14 /avr_de/beginner/rechnen.html 2,772 1.25
15 /avr_en/AVR_DAC.html 2,717 1.23
16 /avr_en/signalgen/rectgen_m8.html 2,646 1.19
17 /avr_en/beginner/REGISTER.html 2,613 1.18
18 /avr_en/beginner/PDETAIL.html 2,576 1.16
19 /avr_de/stepper/stepper.html 2,544 1.15
/avr_en/beginner/COMMANDS.
20 2,508 1.13
html
21 /avr_de/avr_dac.html 2,502 1.13
22 /avr_en/AVR_ADC500.html 2,482 1.12
23 /avr_de/beginner/pdetail.html 2,262 1.02
/avr_de/rechteckgen/rectgen_m8.
24 2,134 0.96
html
25 /avr_de/beginner/commands.html 2,112 0.95
Sum 221,489 100.00

To top of page

Top 25 of 192 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,655 20.28
2 /avr_gra/stk_lcd.jpg 2,086 15.93
3 /avr_gra/8515.jpg 504 3.85
4 /avr_gra/exp2313g.jpg 412 3.15
5 /avr_gra/avr_isp.jpg 404 3.09
6 /avr_gra/exp_2313.jpg 390 2.98
7 /avr_gra/r2r_wave.jpg 308 2.35
8 /avr_gra/r2r_sawtooth.jpg 293 2.24
9 /avr_gra/r2r_sawtooth741.jpg 288 2.20
10 /avr_gra/r2r_hardware.jpg 288 2.20
11 /avr_gra/r2r_sawtoothupperbound.jpg 287 2.19
12 /avr_gra/r2r_triangle.jpg 286 2.18
13 /avr_gra/r2r_upperbound.jpg 285 2.18
14 /avr_gra/AT90S8515.jpg 254 1.94
15 /avr_gra/apps.jpg 226 1.73
16 /avr_gra/pwm_simul.jpg 214 1.63
17 /avr_gra/adc8conn.jpg 212 1.62
18 /akkuload/dscf0030s.jpg 180 1.37
19 /avr_de/stepper/stepper_sm.jpg 174 1.33
/avr_en/signalgen/pics/rectgen_280.
20 173 1.32
jpg
21 /avr_de/stepper/kp4m4-001.jpg 158 1.21
22 /avr_de/fcount/fcount_sm.jpg 157 1.20
23 /avr_de/stepper/driver.jpg 156 1.19
24 /avr_de/stepper/supply.jpg 156 1.19
25 /avr_de/praesentation/zuendtester.jpg 147 1.12
Sum 13,094 100.00

To top of page

Top 25 of 300 GIF-files , sorted by number of files

N GIF-files times %
1 /common/clock.gif 2,101 4.28
/common/knowhow.
2 2,099 4.27
gif
3 /common/app.gif 2,099 4.27
4 /common/akkuload.gif 2,097 4.27
5 /common/example.gif 2,096 4.27
/common/download.
6 2,096 4.27
gif
7 /common/gavrasm.gif 2,095 4.26
8 /common/calc.gif 2,092 4.26
/common/gavrasmw.
9 2,088 4.25
gif
10 /common/beginner.gif 2,087 4.25
11 /common/keyb.gif 2,086 4.25
12 /common/r2r.gif 2,081 4.24
13 /common/adc.gif 2,079 4.23
14 /common/hardware.gif 2,078 4.23
15 /avr_2313.gif 1,411 2.87
16 /dg4fac.gif 1,295 2.64
17 /avr-asm-tutorial.gif 1,290 2.63
18 /avr_gra/2313.gif 1,060 2.16
19 /common/ints.gif 1,049 2.14
20 /common/tn13.gif 1,046 2.13
21 /common/delay.gif 1,042 2.12
22 /avr_gra/exp2313.gif 458 0.93
23 /avr_gra/avr_isp.gif 396 0.81
24 /avr_gra/isp10pin.gif 391 0.80
25 /avr_gra/isp6pin.gif 390 0.79
Sum 49,124 100.00

To top of page

Top 25 of 171 entry pages , sorted by number of files

N entry pages times %


1 /index.html 797 17.85
2 /avr_en/index.html 434 9.72
3 /avr_de/index.html 386 8.64
4 /avr_en/beginner/index.html 222 4.97
5 /avr_de/beginner/index.html 127 2.84
6 /avr_en/AVR_DAC.html 109 2.44
7 /avr_de/fcount/fcount_m8.html 105 2.35
8 /avr_de/stepper/stepper.html 97 2.17
9 /avr_de/avr_dac.html 96 2.15
10 /avr_en/beginner/HARDWARE.html 96 2.15
11 /avr_en/keypad/keyboard.html 80 1.79
12 /avr_en/AVR_ADC500.html 70 1.57
13 /avr_en/signalgen/rectgen_m8.html 68 1.52
14 /avr_de/keypad/keyboard.html 61 1.37
/avr_de/rechteckgen/rectgen_m8.
15 51 1.14
html
16 /gb_new.html 50 1.12
17 /avr_de/rechnen/multiplikation.html 48 1.07
18 /avr_de/rechnen/konversion.html 47 1.05
19 /avr_en/stepper/stepper.html 46 1.03
20 /avr_de/intro/index.html 38 0.85
21 /avr_de/beginner/diraus.html 35 0.78
22 /avr_de/beginner/werkzeuge.html 35 0.78
23 /avr_en/beginner/SRAM.html 34 0.76
24 /avr_de/avr_adc500.html 34 0.76
25 /akkuload/de/index.html 32 0.72
Sum 4,466 100.00

To top of page

Top 25 of 205 cheat pages , sorted by number of files

N cheat pages times %


1 766 13.33
2 /index.html 518 9.01
3 /avr_en/index.html 392 6.82
4 /avr_de/index.html 345 6.00
5 /avr_en/beginner/RIGHT.html 124 2.16
6 /avr_en/AVR_DAC.html 121 2.11
7 /avr_en/beginner/HARDWARE.html 117 2.04
8 /avr_en/keypad/keyboard.html 104 1.81
9 /avr_de/stepper/stepper.html 100 1.74
10 /avr_de/fcount/fcount_m8.html 93 1.62
11 /avr_de/avr_dac.html 92 1.60
12 /avr_de/beginner/rechts.html 81 1.41
13 /avr_de/keypad/keyboard.html 75 1.30
14 /avr_en/AVR_ADC500.html 69 1.20
15 /avr_en/beginner/REGISTER.html 67 1.17
16 /avr_de/beginner/hardware.html 58 1.01
17 /avr_en/signalgen/rectgen_m8.html 58 1.01
18 /akkuload/de/index.html 56 0.97
19 /gb_new.html 53 0.92
20 /avr_en/beginner/JUMP.html 52 0.90
21 /avr_de/beginner/werkzeuge.html 50 0.87
22 /avr_de/beginner/register.html 50 0.87
/avr_de/rechteckgen/rectgen_m8.
23 49 0.85
html
24 /avr_en/stepper/stepper.html 48 0.84
25 /avr_de/rechnen/multiplikation.html 47 0.82
Sum 5,748 100.00

To top of page

Top 25 of 169 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,627 14.88
2 /avr_en/beginner/index.html 1,474 13.48
3 /avr_de/beginner/index.html 807 7.38
4 /avr_en/beginner/RIGHT.html 705 6.45
5 /avr_en/index.html 679 6.21
6 / 672 6.14
7 /avr_en/ 631 5.77
8 /avr_de/beginner/links.html 430 3.93
9 /avr_de/beginner/rechts.html 415 3.79
10 /avr_en/beginner/LEFT.html 383 3.50
11 /sitemap_en.html 283 2.59
12 /sitemap_de.html 195 1.78
13 /avr_de/apps.html 171 1.56
14 /index.html 151 1.38
15 /avr_de/ 148 1.35
16 /avr_de/interrupts/index.html 124 1.13
17 /avr_en/calc/index.html 116 1.06
18 /avr_de/avr_tut.html 111 1.01
19 /avr_en/AVR_TUT.html 108 0.99
20 /avr_de/zeitschleifen/index.html 99 0.91
21 /avr_en/APPS.html 80 0.73
22 /weblox_de/ 67 0.61
23 /weblox_en/ 64 0.59
24 /avr_de/beginner/commands.html 61 0.56
/avr_en/signalgen/rectgen_m8.
25 57 0.52
html
Sum 10,937 100.00

To top of page

Top 25 of 391 external referrers , sorted by number of files

N external referrers times %


1 - 5,327 82.51
2 http://www.mikrocontroller.net/articles/AVR 54 0.84
3 http://www.webring.com/hub?ring=avr 36 0.56
4 http://www.mikrocontroller.net/topic/115233 31 0.48
5 http://avr-asm.tripod.com/ 23 0.36
6 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 23 0.36
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
7 22 0.34
ESC_by1_bz0_bs0.html
8 http://de.wikipedia.org/wiki/R2R-Netzwerk 21 0.33
9 http://www.educypedia.be/electronics/avr.htm 19 0.29
http://www.avrfreaks.net/index.php?
10 name=PNphpBB2&file=viewtopic&t=7067 17 0.26
3
11 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 15 0.23
http://74.125.93.104/translate_c?hl=es&sl=de&u=http://www.avr-asm-tuto
rial.net/sitemap_en.html&prev=/search%3Fq%3Dhttp://www.avr-asm-
12 tutoria 15 0.23
l.net/%26hl%3Des%26sa%
3DG&usg=ALkJrhgAFUPCyAilIOfmCb2KGyBgvf1XqQ
http://electrons.psychogenic.com/modules/arms/art/3/
13 AVRGCCProgrammingG 14 0.22
uide.php
14 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 13 0.20
15 http://www.rowalt.de/mc/avr/linksd.htm 13 0.20
16 http://www.dg4fac.de/rechtsunten.html 13 0.20
http://elektronik-kompendium.de/public/arnerossius/schaltungen/avr/avr
17 12 0.19
kurs.htm
18 http://circuit.lt/?section=sch&page=avr.isp.lpt 12 0.19
19 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 12 0.19
20 http://www.dg4fac.de/linksunten.html 12 0.19
21 http://mathcs.slu.edu/~fritts/csci305_306/links.html 11 0.17
22 http://www.mikrocontroller.net/articles/Linksammlung 11 0.17
23 http://www.attiny.com/avrlinks.htm 11 0.17
24 http://www.sat-ulc.eu/ulc/thread.php?threadid=5730 10 0.15
25 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 10 0.15
Sum 6,456 100.00

To top of page

Top 25 of 126 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,398 42.75
2 http://www.google.com 596 18.23
3 http://www.google.at 100 3.06
4 http://www.google.pl 74 2.26
5 http://www.google.co.in 71 2.17
6 http://www.google.co.uk 69 2.11
7 http://www.google.ch 53 1.62
8 http://www.google.nl 50 1.53
9 http://www.google.ca 43 1.31
10 http://www.google.com.au 36 1.10
11 http://www.google.be 36 1.10
12 http://www.google.it 33 1.01
13 http://www.google.se 32 0.98
14 http://www.google.com.br 30 0.92
15 http://www.google.fi 28 0.86
http://www.google.com.
16 25 0.76
mx
17 http://www.google.co.id 23 0.70
18 http://www.google.hu 22 0.67
19 http://www.google.lt 21 0.64
20 http://www.google.com.ar 19 0.58
21 http://search.yahoo.com 19 0.58
22 http://www.google.co.th 18 0.55
23 http://www.google.si 18 0.55
24 http://www.google.fr 18 0.55
25 http://www.google.ru 17 0.52
Sum 3,270 100.00

To top of page

Top 25 of 2226 search strings , sorted by number of files

N search strings times %


1 avr tutorial 100 3.06
2 avr assembler 67 2.05
3 avr 47 1.44
4 attiny13 34 1.04
5 avr programming 29 0.89
6 assembler 28 0.86
7 AVR tutorial 20 0.61
8 avr assembly 19 0.58
9 assembler commands 17 0.52
10 avr assembler tutorial 16 0.49
11 assembler tutorial 15 0.46
12 avr asm 14 0.43
13 stk500 14 0.43
14 STK500 13 0.40
15 AVR 13 0.40
16 schrittmotor steuerung 11 0.34
17 AVR programming 10 0.31
18 binäre multiplikation 10 0.31
19 atmega8 10 0.31
20 avrasm 9 0.28
assembler
21 9 0.28
programmierung
22 Assembler 9 0.28
23 tutorial avr 8 0.24
24 r2r netzwerk 8 0.24
25 assembler division 8 0.24
Sum 3,270 100.00

To top of page

Top 9 of 9 return codes and messages , sorted by number of files

http://www.avr-asm-tutorial.net/weblox_en/2008w44.html (1 of 2)1/20/2009 8:10:48 PM


Weblog statistic for http://www.avr-asm-tutorial.net

N return codes and messages times %


1 200 OK 81,226 87.16
2 304 Not changed 10,163 10.91
3 206 Partial information 1,454 1.56
4 301 Permanently moved 157 0.17
5 404 File not found 132 0.14
6 403 Forbidden 46 0.05
7 300 Multiple choices 11 0.01
8 xxx Unknown error 3 0.00
9 405 Method not allowed 1 0.00
Sum 93,193 100.00

To top of page

Top 25 of 57 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 23 17.42
2 /beginner_de.pdf 18 13.64
/_vti_bin/owssvr.dll?
3 6 4.55
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
4 6 4.55
UL=1&ACT=4&BUILD=4518&STRMVER=4&CAPREQ=0
5 /avr_de/praesentation/favicon.ico 5 3.79
6 /avr_de/praesentation/favicon.gif 5 3.79
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
7 20la 4 3.03
nguage_files/LEFT.htm
8 /_vti_inf.html 4 3.03
9 /avr_de/beginner/portdetail.html 2 1.52
/_vti_bin/owssvr.dll?
10 2 1.52
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
11 2 1.52
UL=1&ACT=4&BUILD=6551&STRMVER=4&CAPREQ=0
/avr_de/beginner/Anf%C3%A4nger's%20Einf%C3%BChrung%20in%
12 20AVR-Assemble 2 1.52
r-Dateien/links.html
//components/com_extcalendar/admin_events.php?CONFIG_EXT
13 [LANGUAGES_DIR 2 1.52
]=http://125.250.78.194/rgboard/manual/.../sistem.txt???
14 /gavrasm/v16/LiesMich.Txt 2 1.52
/_vti_bin/owssvr.dll?
15 2 1.52
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
16 2 1.52
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
17 20la 2 1.52
nguage_files/RIGHT.htm
18 /avr_de/zeitschleifen/index.html/content.jar 2 1.52
19 /avr_de/zeitschleifen/index.html/content.xml 2 1.52
20 /avr_de/zeitschleifen/index.html/site.xml 2 1.52
21 /avr_gra/beginner/exp2313.gif 1 0.76
22 /akkuload/de/accucalc.asm 1 0.76
/_vti_bin/owssvr.dll?
23 1 0.76
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
24 1 0.76
UL=1&ACT=4&BUILD=2614&STRMVER=4&CAPREQ=0
25 /avr_en/beginner/index.html/url%5D 1 0.76
Sum 132 100.00

To top of page

Top 25 of 110 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 50,455 54.14
2 Mozilla/4.0 34,144 36.64
3 Opera/9.61 1,011 1.08
4 Opera/9.60 929 1.00
5 - 629 0.67
6 Teleport 620 0.67
7 Opera/9.52 499 0.54
8 Opera/9.50 495 0.53
9 msnbot/1.1 473 0.51
10 Yanga 351 0.38
11 Opera/9.62 316 0.34
12 Opera/9.27 277 0.30
13 Mozilla/4.5 274 0.29
14 Opera/9.51 259 0.28
15 Eurobot/1.0 245 0.26
Googlebot-
16 213 0.23
Image/1.0
17 Opera/9.25 210 0.23
18 Opera/9.26 199 0.21
19 Opera/9.22 145 0.16
20 ichiro/3.0 134 0.14
21 Opera/9.23 123 0.13
22 Mozilla/3.01 119 0.13
23 Yandex/1.01.001 112 0.12
24 msnbot-media/1.1 84 0.09
25 Opera/9.10 77 0.08
Sum 93,193 100.00

To top of page

Top 25 of 259 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.3 25,962 27.86
2 MSIE 7.0 17,554 18.84
3 MSIE 6.0 13,633 14.63
4 Firefox/2.0.0.17 6,600 7.08
5 Firefox/3.0.1 2,408 2.58
6 Firefox/3.0.3 2,178 2.34
7 Gecko 2,081 2.23
8 unknown 1,878 2.02
9 Slurp 1,391 1.49
10 Firefox/3.0 1,190 1.28
11 Opera/9.61 1,011 1.08
12 Opera/9.60 929 1.00
13 Firefox/2.0.0.16 702 0.75
14 MSIE 5.0 643 0.69
15 Pro/1.29.1590 620 0.67
16 Firefox/2.0.0.14 585 0.63
17 FDM 501 0.54
18 MSIE 8.0 494 0.53
19 Opera/9.52 484 0.52
20 msnbot/1.1 473 0.51
21 Opera/9.50 469 0.50
22 Firefox/2.0.0.6 449 0.48
23 Avant Browser 446 0.48
24 Firefox/2.0.0.12 398 0.43
25 Firefox/2.0.0.11 381 0.41
Sum 93,193 100.00

To top of page

Top 25 of 46 operating systems , sorted by number of files

N operating systems times %


1 Windows 39,738 42.64
2 Windows NT 5.1 28,890 31.00
3 unknown 6,659 7.15
4 Windows NT 6.0 5,683 6.10
5 Linux i686 5,235 5.62
6 Windows NT 5.0 1,449 1.55
7 Linux x86_64 919 0.99
8 Windows 98 831 0.89
9 Windows NT 4.0 580 0.62
10 Windows NT 5.2 567 0.61
11 Mac OS X 10_5_5 490 0.53
12 Mac OS X 10.5 281 0.30
13 Mac OS X 249 0.27
14 Linux 232 0.25
Mac OS X
15 189 0.20
10_4_11
16 Linux i686 172 0.18
17 Windows XP 5.1 157 0.17
18 Mac OS X 10_5_4 121 0.13
19 Mac OS X 10.4 120 0.13
20 Win16 114 0.12
21 Windows 6.0 68 0.07
22 SunOS sun4u 68 0.07
23 Windows 95 63 0.07
24 Windows Vista 6.0 48 0.05
25 Windows CE 37 0.04
Sum 93,193 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,512 2.70
2 01 2,127 2.28
3 02 1,661 1.78
4 03 1,440 1.55
5 04 1,281 1.37
6 05 1,246 1.34
7 06 1,441 1.55
8 07 2,137 2.29
9 08 3,261 3.50
10 09 4,593 4.93
11 10 4,198 4.50
12 11 4,416 4.74
13 12 5,326 5.72
14 13 6,379 6.84
15 14 6,089 6.53
16 15 6,179 6.63
17 16 4,672 5.01
18 17 5,044 5.41
19 18 4,806 5.16
20 19 4,905 5.26
21 20 5,424 5.82
22 21 5,616 6.03
23 22 4,724 5.07
24 23 3,716 3.99
Sum 93,193 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w44.html (2 of 2)1/20/2009 8:10:48 PM


Weblog statistic for http://www.avr-asm-tutorial.net

Path: Home ==> Log-Index ==> Weekly sorted index ==> Log 2008w42

Weblog statistic for http://www.avr-asm-tutorial.


net
Statistic for the year 2008 , week 42

List, sorted by name times/files bytes visits


IPs and host names - X X -
IPs and host names of multiple visitors - - - X
countries of origin - X - -
pathes - X X -
requested files - X X -
requested pages w/o graphics - X X -
JPEG-files - X - -
GIF-files - X - -
entry pages - X - -
cheat pages - X - -
return codes and messages - X - -
files not found - X - -
internal referrers - X - -
external referrers - X - -
search engines - X - -
search strings - X - -
browser types - X - -
browser versions - X - -
operating systems - X - -
hourly traffic X - - -

Top 25 of 5393 IPs and host names , sorted by number of files

N IPs and host names times %


1 66.249.72.79=crawl-66-249-72-79.googlebot.com 854 0.98
2 90.154.174.194=90-154-174-194.btc-net.bg 668 0.76
3 67.195.37.109=llf320031.crawl.yahoo.net 656 0.75
4 67.68.21.249=bas11-montreal02-1128535545.dsl.bell.ca 587 0.67
5 202.133.89.3=(not found) 559 0.64
6 203.99.187.40=(not found) 449 0.51
7 92.229.113.78=g229113078.adsl.alicedsl.de 395 0.45
8 77.79.25.43=hst-25-43.splius.lt 352 0.40
9 208.115.111.244=crawl3.dotnetdotcom.org 349 0.40
10 77.185.1.113=brln-4db90171.pool.einsundeins.de 343 0.39
11 91.205.124.9=(not found) 342 0.39
71.128.194.49=ppp-71-128-194-49.dsl.sndg02.pacbell.
12 337 0.39
net
13 210.173.180.155=(not found) 335 0.38
14 222.124.24.80=unknown.ugm.ac.id 332 0.38
15 193.189.163.18=panda.telekom.si 289 0.33
16 91.66.11.42=91-66-11-42-dynip.superkabel.de 264 0.30
17 65.55.212.136=(not found) 260 0.30
18 124.137.4.34=(not found) 258 0.29
19 24.2.234.252=c-24-2-234-252.hsd1.ct.comcast.net 243 0.28
20 93.110.90.238=(not found) 233 0.27
21 80.153.105.176=p509969b0.dip0.t-ipconnect.de 232 0.27
22 91.62.220.125=p5B3EDC7D.dip.t-dialin.net 217 0.25
23 84.63.137.112=dslb-084-063-137-112.pools.arcor-ip.net 206 0.24
24 78.94.125.51=ip-78-94-125-51.hsi.ish.de 205 0.23
25 203.199.132.36=proxy1.cdac.in 190 0.22
Sum 87,477 100.00

To top of page

Top 25 of 5393 IPs and host names , sorted by kbytes

N IPs and host names kbytes %


1 90.154.174.194=90-154-174-194.btc-net.bg 16,887 1.98
2 84.186.52.85=p54BA3455.dip0.t-ipconnect.de 14,278 1.67
3 66.249.72.79=crawl-66-249-72-79.googlebot.com 11,894 1.39
4 203.99.187.40=(not found) 9,945 1.16
5 92.229.113.78=g229113078.adsl.alicedsl.de 8,091 0.95
6 77.185.1.113=brln-4db90171.pool.einsundeins.de 7,679 0.90
7 67.195.37.109=llf320031.crawl.yahoo.net 7,152 0.84
8 84.113.191.140=chello084113191140.2.13.vie.surfer.at 6,681 0.78
9 202.133.89.3=(not found) 6,448 0.75
10 87.170.121.185=p57AA79B9.dip.t-dialin.net 5,698 0.67
11 91.14.107.184=p5B0E6BB8.dip.t-dialin.net 4,923 0.58
83.171.190.183=DSL01.83.171.190.183.ip-pool.NEFkom.
12 4,840 0.57
net
13 62.134.199.5=(not found) 4,680 0.55
14 78.94.125.51=ip-78-94-125-51.hsi.ish.de 4,518 0.53
15 79.198.87.109=p4FC6576D.dip.t-dialin.net 4,225 0.49
16 210.173.180.155=(not found) 4,001 0.47
17 77.183.132.28=gels-4db7841c.pool.einsundeins.de 3,830 0.45
18 84.63.137.112=dslb-084-063-137-112.pools.arcor-ip.net 3,784 0.44
19 217.6.15.137=(not found) 3,704 0.43
20 80.64.83.125=l64-83-125.cn.ru 3,602 0.42
21 89.244.207.26=i59F4CF1A.versanet.de 3,452 0.40
22 91.205.124.9=(not found) 3,440 0.40
23 141.24.104.59=klaus.physik.tu-ilmenau.de 3,414 0.40
24 208.115.111.244=crawl3.dotnetdotcom.org 3,356 0.39
25 222.124.24.80=unknown.ugm.ac.id 3,140 0.37
Sum 854,496 100.00

To top of page

Top 25 of 867 IPs and host names of multiple visitors , sorted by number
of visits

N IPs and host names of multiple visitors visits %


1 67.195.37.109=llf320031.crawl.yahoo.net 113 3.45
2 66.249.72.79=crawl-66-249-72-79.googlebot.com 108 3.30
3 88.134.89.107=88-134-89-107-dynip.superkabel.de 37 1.13
4 193.47.80.44=crawl8.exabot.com 28 0.86
5 80.77.80.253=(not found) 26 0.79
6 65.55.212.136=(not found) 24 0.73
7 88.131.106.16=ca0.entireweb.com 24 0.73
8 38.99.13.125=crawl-4.cuill.com 23 0.70
9 88.156.163.76=76.163.rze.vectranet.pl 22 0.67
10 91.66.11.42=91-66-11-42-dynip.superkabel.de 22 0.67
11 81.52.143.16=natcrawlbloc03.net.m1.fti.net 21 0.64
12 193.252.149.15=natcrawlbloc02.net.s1.fti.net 20 0.61
13 80.108.152.73=chello080108152073.4.12.vie.surfer.at 19 0.58
65.55.209.167=msnbot-65-55-209-167.search.msn.
14 18 0.55
com
15 85.18.227.211=85-18-227-211.ip.fastwebnet.it 17 0.52
16 81.52.143.15=natcrawlbloc01.net.m1.fti.net 17 0.52
17 65.55.232.17=(not found) 17 0.52
18 58.251.108.173=reverse.gdsz.cncnet.net 17 0.52
19 131.181.251.67=proxy2-mercury.net.qut.edu.au 15 0.46
20 81.200.20.91=(not found) 15 0.46
65.55.230.204=msnbot-65-55-230-204.search.msn.
21 15 0.46
com
65.55.209.150=msnbot-65-55-209-150.search.msn.
22 15 0.46
com
23 88.118.153.89=(not found) 14 0.43
24 65.55.25.140=(not found) 14 0.43
25 202.160.179.44=lj910230.crawl.yahoo.net 14 0.43
Sum 3,271 100.00

To top of page

Top 25 of 96 countries of origin , sorted by number of files

N countries of origin times %


1 net 21,414 24.48
2 Germany 19,395 22.17
3 (unresolved) 18,399 21.03
4 com 5,274 6.03
5 Poland 2,026 2.32
6 Austria 1,894 2.17
7 Canada 1,115 1.27
8 Switzerland 957 1.09
9 Lithuania 947 1.08
10 India 922 1.05
11 Australia 918 1.05
12 Bulgaria 824 0.94
13 Netherlands 783 0.90
14 Romania 743 0.85
15 Sweden 682 0.78
16 Hungary 650 0.74
17 Indonesia 606 0.69
18 Italy 590 0.67
19 Brazil 575 0.66
20 edu 570 0.65
21 Mexico 536 0.61
22 Russian Federation 487 0.56
23 Finland 465 0.53
24 Norway 434 0.50
25 United Kingdom 408 0.47
Sum 87,477 100.00

To top of page

Top 25 of 158 pathes , sorted by number of files

N pathes times %
1 /common/ 30,138 34.45
2 /avr_gra/ 15,594 17.83
3 / 9,924 11.34
4 /avr_en/beginner/ 4,259 4.87
5 /avr_en/ 2,949 3.37
6 /avr_de/beginner/ 2,680 3.06
7 /avr_de/ 2,406 2.75
8 /avr_en/calc/ 1,852 2.12
9 /avr_de/fcount/ 1,232 1.41
10 /avr_en/source/ 1,202 1.37
11 /avr_de/rechnen/ 1,185 1.35
12 /avr_en/keypad/ 1,076 1.23
13 /avr_de/stepper/ 957 1.09
14 /avr_en/signalgen/pics/ 956 1.09
15 /avr_de/praesentation/ 908 1.04
16 /avr_de/quellen/ 874 1.00
17 /avr_en/stepper/ 737 0.84
18 /avr_de/keypad/ 724 0.83
19 /avr_de/rechteckgen/bilder/ 630 0.72
20 /gavrasm/ 614 0.70
21 /avr_de/zeitschleifen/ 466 0.53
22 /avr_de/interrupts/ 383 0.44
23 /avr_en/signalgen/ 370 0.42
/privat/stechlin/rundgang/
24 340 0.39
thumbs/
25 /privat/kranichstein/thumbs/ 329 0.38
Sum 87,477 100.00

To top of page

Top 25 of 158 pathes , sorted by kbytes

N pathes kbytes %
1 /avr_de/praesentation/ 148,802 17.41
2 /avr_gra/ 123,901 14.50
3 / 56,185 6.58
4 /avr_de/intro/pdf/ 49,892 5.84
5 /avr_de/fcount/ 47,612 5.57
6 /avr_en/ 40,986 4.80
7 /avr_de/ 38,545 4.51
8 /avr_en/beginner/ 37,920 4.44
9 /avr_de/beginner/ 26,010 3.04
10 /avr_de/stepper/ 24,009 2.81
11 /avr_en/signalgen/pics/ 23,974 2.81
12 /avr_en/stepper/ 17,522 2.05
13 /gavrasm/v21/ 17,367 2.03
14 /avr_en/calc/ 16,902 1.98
15 /avr_de/rechteckgen/bilder/ 16,304 1.91
16 /common/ 14,326 1.68
17 /avr_en/signalgen/ 13,071 1.53
18 /avr_de/rechnen/ 11,319 1.32
19 /avr_de/rechteckgen/ 9,156 1.07
/privat/stechlin/2005juni/
20 8,850 1.04
meilenweit/
21 /privat/kranichstein/thumbs/ 8,272 0.97
22 /avr_en/keypad/ 7,902 0.92
23 /privat/magloop/ 7,618 0.89
24 /akkuload/ 7,183 0.84
25 /avr_en/source/ 5,875 0.69
Sum 854,496 100.00

To top of page

Top 25 of 1376 requested files , sorted by number of files

N requested files times %


1 /favicon.ico 4,398 5.03
2 /avr_gra/RingLogo.jpg 2,373 2.71
3 /common/calc.gif 1,963 2.24
/common/knowhow.
4 1,963 2.24
gif
5 /common/clock.gif 1,962 2.24
6 /common/gavrasm.gif 1,961 2.24
7 /common/app.gif 1,961 2.24
/common/download.
8 1,960 2.24
gif
9 /common/example.gif 1,959 2.24
10 /avr_gra/stk_lcd.jpg 1,958 2.24
/common/gavrasmw.
11 1,958 2.24
gif
12 /common/akkuload.gif 1,958 2.24
13 /common/adc.gif 1,957 2.24
14 /common/beginner.gif 1,956 2.24
15 /common/r2r.gif 1,953 2.23
16 /common/hardware.gif 1,951 2.23
17 /common/keyb.gif 1,944 2.22
18 /index.html 1,384 1.58
19 /avr_en/index.html 1,259 1.44
20 /avr_de/index.html 1,037 1.19
21 /avr_gra/2313.gif 1,027 1.17
22 /dg4fac.gif 1,026 1.17
23 /avr_2313.gif 1,020 1.17
24 /avr-asm-tutorial.gif 1,016 1.16
25 /common/ints.gif 913 1.04
Sum 87,477 100.00

To top of page

Top 25 of 1376 requested files , sorted by kbytes

N requested files kbytes %


1 /avr_de/praesentation/Anwendungsbeispiele.pdf 47,501 5.56
2 /avr_de/praesentation/Teil_6_Beispiel03_07.pdf 27,939 3.27
3 /avr_en/index.html 26,032 3.05
4 /avr_de/index.html 23,018 2.69
5 /avr_de/praesentation/Teil_8_Beispiel_11.pdf 21,175 2.48
6 /avr_2313.gif 18,236 2.13
7 /avr_de/praesentation/Teil_7_Beispiel08_10.pdf 15,770 1.85
8 /avr_de/intro/pdf/Teil6_Beispiel03_07.pdf 14,625 1.71
/avr_de/praesentation/Teil_5b_Beispiel01_02.
9 13,930 1.63
pdf
10 /avr_de/intro/pdf/Teil7_Beispiel08_10.pdf 11,047 1.29
11 /dg4fac.gif 11,006 1.29
12 /avr_en/signalgen/pics/rectgen_wiring.jpg 10,917 1.28
13 /avr_gra/r2r_hardware.jpg 10,490 1.23
14 /avr_gra/pwm_simul.jpg 10,169 1.19
15 /avr_de/fcount/dscf0004.jpg 9,281 1.09
16 /favicon.ico 8,598 1.01
17 /avr_de/intro/pdf/Teil5b_Beispiel01_02.pdf 8,230 0.96
18 /avr_gra/exp2313.gif 8,151 0.95
19 /avr_de/praesentation/Teil_4_AufbauTiny13.pdf 8,005 0.94
20 /avr_de/fcount/dscf0005.jpg 8,004 0.94
21 /avr_de/fcount/dscf0001.jpg 7,626 0.89
22 /avr_de/intro/pdf/AVREinfuehrung_pdf.zip 7,526 0.88
23 /avr_de/rechteckgen/bilder/rectgen_wiring.jpg 7,469 0.87
24 /avr_gra/2313.gif 7,400 0.87
25 /index.html 7,226 0.85
Sum 854,496 100.00

To top of page

Top 25 of 358 requested pages w/o graphics , sorted by number of files

N requested pages w/o graphics times %


1 /index.html 1,384 7.20
2 /avr_en/index.html 1,259 6.55
3 /avr_de/index.html 1,037 5.39
4 /avr_en/beginner/index.html 716 3.72
5 /avr_en/beginner/LEFT.html 691 3.59
6 /avr_en/beginner/RIGHT.html 690 3.59
7 /avr_de/beginner/index.html 424 2.20
8 /avr_de/beginner/links.html 405 2.11
9 /avr_de/beginner/rechts.html 405 2.11
/avr_en/beginner/HARDWARE.
10 333 1.73
html
11 /avr_en/beginner/REGISTER.html 253 1.32
12 /avr_en/keypad/keyboard.html 224 1.16
13 /avr_en/beginner/JUMP.html 215 1.12
14 /avr_en/AVR_DAC.html 191 0.99
15 /avr_en/beginner/TOOLS.html 172 0.89
16 /avr_en/beginner/CALC.html 165 0.86
17 /avr_en/beginner/SRAM.html 162 0.84
18 /avr_en/beginner/PORTS.html 158 0.82
19 /avr_en/signalgen/rectgen_m8.html 158 0.82
20 /avr_de/beginner/hardware.html 153 0.80
21 /avr_de/beginner/register.html 149 0.77
22 /avr_de/keypad/keyboard.html 147 0.76
23 /avr_de/praesentation/index.html 146 0.76
24 /avr_en/AVR_TUT.html 144 0.75
25 /avr_de/apps.html 142 0.74
Sum 19,233 100.00

To top of page

Top 25 of 358 requested pages w/o graphics , sorted by kbytes

N requested pages w/o graphics kbytes %


1 /avr_en/index.html 26,032 12.12
2 /avr_de/index.html 23,018 10.72
3 /index.html 7,226 3.36
4 /gb_new.html 5,551 2.58
5 /avr_en/beginner/JUMP.html 5,248 2.44
6 /avr_en/beginner/RIGHT.html 5,120 2.38
7 /avr_en/keypad/keyboard.html 4,593 2.14
8 /avr_de/dcf77uhr.html 4,374 2.04
9 /avr_en/beginner/CALC.html 4,028 1.88
10 /avr_de/beginner/sprung.html 3,720 1.73
11 /avr_en/beginner/LEFT.html 3,248 1.51
12 /avr_en/beginner/REGISTER.html 3,159 1.47
13 /avr_en/signalgen/rectgen_m8.html 2,979 1.39
14 /avr_de/keypad/keyboard.html 2,970 1.38
15 /avr_de/beginner/rechnen.html 2,916 1.36
16 /avr_en/beginner/PDETAIL.html 2,885 1.34
17 /avr_en/AVR_DAC.html 2,840 1.32
18 /avr_de/beginner/rechts.html 2,792 1.30
/avr_en/beginner/COMMANDS.
19 2,684 1.25
html
20 /avr_en/beginner/HARDWARE.html 2,485 1.16
21 /avr_de/avr_dac.html 2,376 1.11
22 /avr_en/AVR_ADC500.html 2,295 1.07
23 /avr_de/beginner/commands.html 2,244 1.04
/avr_de/rechteckgen/rectgen_m8.
24 2,213 1.03
html
25 /sitemap_de.html 2,210 1.03
Sum 214,816 100.00

To top of page

Top 25 of 396 JPEG-files , sorted by number of files

N JPEG-files times %
1 /avr_gra/RingLogo.jpg 2,373 18.42
2 /avr_gra/stk_lcd.jpg 1,958 15.20
3 /avr_gra/8515.jpg 495 3.84
4 /avr_gra/avr_isp.jpg 450 3.49
5 /avr_gra/exp2313g.jpg 441 3.42
6 /avr_gra/exp_2313.jpg 437 3.39
7 /avr_gra/r2r_wave.jpg 309 2.40
8 /avr_gra/r2r_hardware.jpg 290 2.25
9 /avr_gra/r2r_sawtooth.jpg 290 2.25
10 /avr_gra/r2r_triangle.jpg 283 2.20
11 /avr_gra/r2r_sawtoothupperbound.jpg 281 2.18
12 /avr_gra/r2r_sawtooth741.jpg 281 2.18
13 /avr_gra/r2r_upperbound.jpg 277 2.15
14 /avr_gra/AT90S8515.jpg 217 1.68
15 /avr_en/signalgen/pics/rectgen_280.jpg 197 1.53
16 /avr_gra/adc8conn.jpg 186 1.44
17 /avr_gra/pwm_simul.jpg 181 1.41
18 /avr_gra/apps.jpg 174 1.35
19 /avr_en/signalgen/pics/rectgen_wiring.jpg 147 1.14
20 /akkuload/dscf0030s.jpg 138 1.07
21 /avr_de/stepper/stepper_sm.jpg 138 1.07
/avr_de/rechteckgen/bilder/rectgen_280.
22 133 1.03
jpg
23 /avr_de/stepper/kp4m4-001.jpg 128 0.99
24 /avr_de/praesentation/zuendtester.jpg 128 0.99
25 /avr_de/stepper/supply.jpg 123 0.95
Sum 12,881 100.00

To top of page

Top 25 of 326 GIF-files , sorted by number of files

N GIF-files times %
1 /common/calc.gif 1,963 4.30
/common/knowhow.
2 1,963 4.30
gif
3 /common/clock.gif 1,962 4.30
4 /common/gavrasm.gif 1,961 4.30
5 /common/app.gif 1,961 4.30
/common/download.
6 1,960 4.30
gif
7 /common/example.gif 1,959 4.29
/common/gavrasmw.
8 1,958 4.29
gif
9 /common/akkuload.gif 1,958 4.29
10 /common/adc.gif 1,957 4.29
11 /common/beginner.gif 1,956 4.29
12 /common/r2r.gif 1,953 4.28
13 /common/hardware.gif 1,951 4.28
14 /common/keyb.gif 1,944 4.26
15 /avr_gra/2313.gif 1,027 2.25
16 /dg4fac.gif 1,026 2.25
17 /avr_2313.gif 1,020 2.24
18 /avr-asm-tutorial.gif 1,016 2.23
19 /common/ints.gif 913 2.00
20 /common/delay.gif 912 2.00
21 /common/tn13.gif 906 1.99
22 /avr_gra/exp2313.gif 456 1.00
23 /avr_gra/avr_isp.gif 442 0.97
24 /avr_gra/isp10pin.gif 440 0.96
25 /avr_gra/isp6pin.gif 438 0.96
Sum 45,622 100.00

To top of page

Top 25 of 191 entry pages , sorted by number of files

N entry pages times %


1 /index.html 692 16.24
2 /avr_en/index.html 475 11.15
3 /avr_de/index.html 356 8.35
4 /avr_en/beginner/index.html 252 5.91
5 /avr_en/AVR_DAC.html 118 2.77
6 /avr_de/beginner/index.html 104 2.44
7 /avr_en/beginner/HARDWARE.html 93 2.18
8 /avr_de/avr_dac.html 80 1.88
9 /avr_en/keypad/keyboard.html 73 1.71
10 /avr_de/keypad/keyboard.html 68 1.60
11 /avr_de/stepper/stepper.html 66 1.55
12 /avr_en/AVR_ADC500.html 60 1.41
13 /avr_de/fcount/fcount_m8.html 59 1.38
14 /avr_en/signalgen/rectgen_m8.html 58 1.36
15 /gb_new.html 57 1.34
16 /avr_en/stepper/stepper.html 50 1.17
/avr_de/rechteckgen/rectgen_m8.
17 49 1.15
html
18 /avr_en/beginner/REGISTER.html 43 1.01
19 /avr_en/calc/CONVERSION.html 43 1.01
20 /avr_de/rechnen/multiplikation.html 43 1.01
21 /avr_de/intro/index.html 39 0.92
22 /avr_de/rechnen/konversion.html 38 0.89
23 /privat/stechlin/index.html 37 0.87
24 /avr_en/beginner/SRAM.html 34 0.80
25 /avr_de/beginner/hardware.html 33 0.77
Sum 4,262 100.00

To top of page

Top 25 of 234 cheat pages , sorted by number of files

N cheat pages times %


1 642 11.90
2 /index.html 452 8.38
3 /avr_en/index.html 404 7.49
4 /avr_de/index.html 271 5.03
5 /avr_en/beginner/RIGHT.html 137 2.54
6 /avr_en/AVR_DAC.html 136 2.52
7 /avr_en/beginner/HARDWARE.html 126 2.34
8 /avr_en/keypad/keyboard.html 106 1.97
9 /avr_de/avr_dac.html 83 1.54
10 /avr_en/beginner/REGISTER.html 81 1.50
11 /avr_de/keypad/keyboard.html 79 1.46
12 /avr_en/AVR_ADC500.html 75 1.39
13 /avr_en/beginner/JUMP.html 71 1.32
14 /avr_en/signalgen/rectgen_m8.html 68 1.26
15 /avr_de/stepper/stepper.html 64 1.19
16 /avr_de/beginner/rechts.html 63 1.17
17 /avr_de/fcount/fcount_m8.html 60 1.11
18 /avr_de/beginner/werkzeuge.html 54 1.00
19 /avr_de/beginner/hardware.html 51 0.95
20 /avr_en/beginner/CALC.html 48 0.89
21 /avr_en/beginner/TOOLS.html 48 0.89
22 /gb_new.html 48 0.89
/avr_de/rechteckgen/rectgen_m8.
23 47 0.87
html
24 /avr_en/calc/CONVERT.html 47 0.87
25 /avr_de/beginner/register.html 46 0.85
Sum 5,393 100.00

To top of page

Top 25 of 157 internal referrers , sorted by number of files

N internal referrers times %


1 /avr_de/index.html 1,275 13.38
2 /avr_en/beginner/index.html 1,224 12.84
3 /avr_de/beginner/index.html 726 7.62
4 /avr_en/ 705 7.40
5 /avr_en/beginner/RIGHT.html 619 6.49
6 /avr_en/index.html 600 6.29
7 / 560 5.87
8 /avr_en/beginner/LEFT.html 460 4.83
9 /avr_de/beginner/rechts.html 414 4.34
10 /sitemap_de.html 302 3.17
11 /avr_de/beginner/links.html 255 2.68
12 /sitemap_en.html 221 2.32
13 /index.html 132 1.38
14 /avr_de/apps.html 129 1.35
15 /avr_de/interrupts/index.html 107 1.12
16 /avr_de/ 107 1.12
17 /avr_en/calc/index.html 104 1.09
18 /avr_en/AVR_TUT.html 101 1.06
19 /avr_de/zeitschleifen/index.html 96 1.01
20 /avr_de/avr_tut.html 90 0.94
/avr_en/signalgen/rectgen_m8.
21 78 0.82
html
22 /avr_en/APPS.html 71 0.74
23 /avr_de/rechnen/index.html 65 0.68
24 /avr_en/AVR_SOFT.html 49 0.51
25 /avr_de/beginner/commands.html 45 0.47
Sum 9,532 100.00

To top of page

Top 25 of 374 external referrers , sorted by number of files

N external referrers times %


1 - 5,242 84.86
2 http://www.mikrocontroller.net/articles/AVR 36 0.58
3 http://www.webring.com/hub?ring=avr 26 0.42
4 http://de.wikipedia.org/wiki/R2R-Netzwerk 24 0.39
5 http://www.dg4fac.de/linksunten.html 18 0.29
http://forum.electronicwerkstatt.de/phpBB/topic7388_f28_bxtopic_timexD
6 18 0.29
ESC_by1_bz0_bs0.html
http://www.elektronik-kompendium.de/public/arnerossius/schaltungen/avr
7 18 0.29
/avrkurs.htm
8 http://www.educypedia.be/electronics/avr.htm 16 0.26
9 http://www.mikrocontroller.net/articles/Linksammlung 15 0.24
10 http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack 14 0.23
11 http://avr-asm.tripod.com/ 13 0.21
12 http://www.mikrocontroller.net/topic/10424 12 0.19
13 http://weblogs.asp.net/jmoon/archive/2005/07/08/418559.aspx 11 0.18
14 http://www.edw.com.pl/ea/asm_avr_jezyk.html 11 0.18
15 http://www.todopic.com.ar/foros/index.php?topic=1121.0;do=Bookmark 11 0.18
http://electrons.psychogenic.com/modules/arms/art/3/
16 AVRGCCProgrammingG 10 0.16
uide.php
http://www.avrfreaks.net/index.php?
17 name=PNphpBB2&file=viewtopic&t=7000 10 0.16
8
18 http://www.htw-dresden.de/~beck/Atmel/ATmegaLinks.html 10 0.16
19 http://www.transmic.net/gb89c2051.htm 10 0.16
20 http://forum.mikrokontrolery.net/viewtopic.php?t=1631 9 0.15
http://www.avrfreaks.net/index.php?
21 name=PNphpBB2&file=viewtopic&t=3698 9 0.15
8
22 http://frank.bol.ucla.edu/avr.htm 9 0.15
23 http://www.dg4fac.de/rechtsunten.html 9 0.15
24 http://www.bitartist.org/2008/07/avr-assembler-tutorial.html 8 0.13
25 http://en.wikibooks.org/wiki/Embedded_Systems/Atmel_AVR 8 0.13
Sum 6,177 100.00

To top of page

Top 25 of 125 search engines , sorted by number of files

N search engines times %


1 http://www.google.de 1,236 37.80
2 http://www.google.com 702 21.47
3 http://www.google.at 103 3.15
4 http://www.google.co.in 97 2.97
5 http://www.google.co.uk 69 2.11
6 http://www.google.com.au 69 2.11
7 http://www.google.ch 66 2.02
8 http://www.google.ca 63 1.93
9 http://www.google.pl 57 1.74
10 http://www.google.se 39 1.19
11 http://www.google.nl 34 1.04
12 http://www.google.ro 32 0.98
13 http://www.google.co.id 30 0.92
14 http://www.google.hu 30 0.92
15 http://search.live.com 30 0.92
16 http://www.google.fi 28 0.86
17 http://www.google.it 27 0.83
18 http://de.search.yahoo.com 26 0.80
19 http://www.google.fr 23 0.70
20 http://www.google.com.br 23 0.70
21 http://www.google.co.th 22 0.67
22 http://www.google.lt 15 0.46
23 http://www.google.gr 15 0.46
http://forum.mikrokontrolery.
24 14 0.43
net
25 http://www.google.com.mx 14 0.43
Sum 3,270 100.00

To top of page

Top 25 of 2248 search strings , sorted by number of files

N search strings times %


1 avr tutorial 86 2.63
2 avr assembler 60 1.83
3 avr programming 53 1.62
4 avr 37 1.13
5 attiny13 31 0.95
6 assembler 26 0.80
7 assembler tutorial 22 0.67
8 avr assembly tutorial 14 0.43
9 atmega8 14 0.43
10 avr assembly 13 0.40
11 ATtiny13 13 0.40
12 7377 13 0.40
13 avr asm 13 0.40
14 avr asm tutorial 12 0.37
15 assembler commands 12 0.37
16 avr assembler tutorial 12 0.37
17 atmega8 tutorial 10 0.31
18 tastatur matrix 9 0.28
19 Assembler 9 0.28
20 assembler avr 9 0.28
21 tutorial 9 0.28
site:www.avr-asm-tutorial.net avr lcd routine OR library -bascom -
22 win 9 0.28
avr -gcc
23 atmega tutorial 8 0.24
24 AVR programming 8 0.24
25 avr tutorials 7 0.21
Sum 3,270 100.00

To top of page

Top 7 of 7 return codes and messages , sorted by number of files

N return codes and messages times %


1 200 OK 78,500 89.74
2 304 Not changed 7,435 8.50
3 206 Partial information 1,169 1.34
4 301 Permanently moved 169 0.19

http://www.avr-asm-tutorial.net/weblox_en/2008w42.html (1 of 2)1/20/2009 8:11:47 PM


Weblog statistic for http://www.avr-asm-tutorial.net

5 404 File not found 163 0.19


6 403 Forbidden 32 0.04
7 300 Multiple choices 9 0.01
Sum 87,477 100.00

To top of page

Top 25 of 83 files not found , sorted by number of files

N files not found times %


1 /beginner_en.pdf 37 22.70
2 /beginner_de.pdf 18 11.04
/_vti_bin/owssvr.dll?
3 6 3.68
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
4 6 3.68
UL=1&ACT=4&BUILD=8164&STRMVER=4&CAPREQ=0
5 /avr_de/intro/ppt/beispiel10_snd.wav 4 2.45
//decoder/markdown.php?ccms_library_path=http://www.voltaique.com/admi
6 4 2.45
nistrator/components/com_login/id.txt???
7 /avr_en/source/stepmotor_v1.asm 3 1.84
8 /avr_de/cq-dl/index.html 2 1.23
9 /avr_en/source/TEST1.asm 2 1.23
10 /avr_en/beginner/2313.gif 2 1.23
/_vti_bin/owssvr.dll?
11 2 1.23
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
/MSOffice/cltreq.asp?
12 2 1.23
UL=1&ACT=4&BUILD=6403&STRMVER=4&CAPREQ=0
13 /SlurpConfirm404.htm 2 1.23
/avr_de/remote.html//decoder/markdown.php?ccms_library_path=http://www
14 2 1.23
.voltaique.com/administrator/components/com_login/id.txt???
/avr_de//decoder/markdown.php?ccms_library_path=http://www.voltaique.c
15 2 1.23
om/administrator/components/com_login/id.txt???
16 /_vti_inf.html 2 1.23
17 /avr_en/beginner/exp_2313.jpg 1 0.61
18 /avr_en/beginner/isp6pin.gif 1 0.61
19 /avr_en/beginner/avr_isp.gif 1 0.61
20 /avr_en/beginner/isp10pin.gif 1 0.61
21 /avr_en/beginner/avr_isp.jpg 1 0.61
22 /avr_en/beginner/exp2313.gif 1 0.61
23 /avr_en/beginner/exp2313g.jpg 1 0.61
24 /avr_de/keypad/keyboard.html/index.html 1 0.61
/avr_en/beginner/Beginner's%20introduction%20to%20AVR%20assembler%
25 20la 1 0.61
nguage_files/LEFT.htm
Sum 163 100.00

To top of page

Top 25 of 103 browser types , sorted by number of files

N browser types times %


1 Mozilla/5.0 46,120 52.72
2 Mozilla/4.0 33,363 38.14
3 Opera/9.60 1,595 1.82
4 Opera/9.52 1,077 1.23
5 Mozilla/4.5 615 0.70
6 Opera/9.51 572 0.65
7 yacybot 473 0.54
8 msnbot/1.1 382 0.44
9 Yanga 342 0.39
10 ichiro/3.0 340 0.39
11 Opera/9.25 282 0.32
12 Opera/9.50 278 0.32
13 msnbot-media/1.0 260 0.30
Googlebot-
14 253 0.29
Image/1.0
15 Opera/9.27 209 0.24
16 msnbot-media/1.1 191 0.22
17 Opera/9.21 187 0.21
18 - 106 0.12
19 CCBot/1.0 76 0.09
20 Opera/9.10 67 0.08
21 Opera/9.26 60 0.07
22 ia_archiver 50 0.06
23 Speedy 42 0.05
24 Opera/9.24 40 0.05
25 Opera/9.00 32 0.04
Sum 87,477 100.00

To top of page

Top 25 of 261 browser versions , sorted by number of files

N browser versions times %


1 Firefox/3.0.3 22,544 25.77
2 MSIE 7.0 15,430 17.64
3 MSIE 6.0 14,715 16.82
4 Firefox/2.0.0.17 4,893 5.59
5 Firefox/3.0.1 2,989 3.42
6 Gecko 2,376 2.72
7 Firefox/3.0.3 1,815 2.07
8 Opera/9.60 1,579 1.81
9 MSIE 5.0 1,479 1.69
10 Slurp 1,376 1.57
11 unknown 1,129 1.29
12 Opera/9.52 1,065 1.22
13 Firefox/2.0.0.16 855 0.98
14 Firefox/3.0 775 0.89
15 Firefox/2.0.0.14 624 0.71
16 HTTrack 3.0x 602 0.69
17 Googlebot/2.1 597 0.68
18 Firefox/2.0.0.6 574 0.66
19 Opera/9.51 572 0.65
20 yacybot 473 0.54
21 Firefox/3.0.2 454 0.52
Gecko/2008071618
22 398 0.45
Iceweasel/3.0.1
23 msnbot/1.1 382 0.44
24 FDM 375 0.43
25 Firefox/2.0.0.13 366 0.42
Sum 87,477 100.00

To top of page

Top 25 of 45 operating systems , sorted by number of files

N operating systems times %


1 Windows 35,187 40.22
2 Windows NT 5.1 28,507 32.59
3 unknown 5,929 6.78
4 Linux i686 5,214 5.96
5 Windows NT 6.0 4,196 4.80
6 Windows NT 5.0 2,095 2.39
7 Windows 98 1,321 1.51
8 Linux x86_64 1,145 1.31
9 Windows NT 4.0 1,120 1.28
10 Windows XP 5.1 640 0.73
11 Mac OS X 10_5_5 360 0.41
12 Windows NT 5.2 349 0.40
13 Linux 310 0.35
14 Mac OS X 10.5 306 0.35
15 Mac OS X 167 0.19
16 Mac OS X 10_4_11 129 0.15
17 Mac OS X 10.4 123 0.14
18 Mac OS X 10_5_4 79 0.09
19 Linux i686 50 0.06
20 Kubuntu 47 0.05
21 Kubuntu 6.06 Dapper 29 0.03
22 Windows 6.0 28 0.03
23 SunOS i86pc 21 0.02
Linux 2.6.24-19-
24 18 0.02
generic
25 FreeBSD 14 0.02
Sum 87,477 100.00

To top of page

Top 24 of 24 hourly traffic , sorted by hour

N hourly traffic files %


1 00 2,518 2.88
2 01 1,809 2.07
3 02 1,813 2.07
4 03 1,342 1.53
5 04 1,299 1.48
6 05 2,353 2.69
7 06 1,882 2.15
8 07 1,833 2.10
9 08 2,634 3.01
10 09 4,338 4.96
11 10 3,547 4.05
12 11 4,510 5.16
13 12 4,164 4.76
14 13 4,327 4.95
15 14 5,105 5.84
16 15 5,139 5.87
17 16 5,341 6.11
18 17 4,321 4.94
19 18 5,608 6.41
20 19 4,618 5.28
21 20 5,429 6.21
22 21 5,223 5.97
23 22 4,985 5.70
24 23 3,339 3.82
Sum 87,477 100.00

To top of page

©2007 by http://www.avr-asm-tutorial.net
Created with Weblox, version 0.9b, freeware by the author dg4fac, see http://www.dg4fac.de

http://www.avr-asm-tutorial.net/weblox_en/2008w42.html (2 of 2)1/20/2009 8:11:47 PM

Vous aimerez peut-être aussi