Exempel 4. Användning av en timer

Relevanta dokument
General Purpose registers ALU I T H S V N Z C SREG. Antag att vi behöver skriva in talet 25 till register R18

AVR 3 - datorteknik. Avbrott. Digitala system 15 hp. Förberedelser

Dataminne I/O Stack 0x005D 0x3D SP low byte 0x005E 0x3E SP high byte

A-del motsvarande KS1

Programräknaren visar alltid på nästa instruktion som skall utföras. Så fort en instruktion har hämtats så visar programräknaren på nästa instruktion.

Kontrollskrivning Mikrodatorteknik CDT S2-704

Minnen delas in i två huvudgrupper, permanenta och icke permanenta. Non-volatile and volatile.

Ansvarig lärare: Olof Andersson, Telefon (besöker skrivsalen)

CE_O3. Nios II. Inför lab nios2time

Att läsa en manual. Exempel Timern ECT_16B8C. Läs den allmänna beskrivningen (Overview) Vi ser att grundfunktionen är en räknare med prescaler

Datorteknik Hyfsa kod

Laboration 4: Knappstuds Drivrutiner för att eliminera störningar.

Ett program som frågar regelbundet om något skall utföras. Exempelvis om spänningen på ett batteri sjunkit under en viss nivå.

F8: Undantagshantering

Digital- och datorteknik

Svar till Övning3 Datorteknik, HH vt12 Avbrott och timers

Laboration 5 C-programmering på AVR TSEA57 Datorteknik I

Lösningar till tentamen i EIT070 Datorteknik

LABORATION. Datorteknik Y

CE_O6. Parallell in/utmatning (I/O). Förberedelser till laboration nios2io.

Växtviskaren EITF11 Digitala projekt VT15, I12

TENTAMEN Datorteknik (DO2005) D1/E1/Mek1/Ö1

AVRStudio på tre minuter. Micke Josefsson, 2005

Provmoment: Ladokkod: Tentamen ges för: Tentamen TE111B El3. Namn: Personnummer: Tentamensdatum: Tid: 14:00-18:00.

Laboration 2 i Datorteknik- Assemblerprogrammering II

Systemkonstruktion LABORATION REALTIDSPROGRAMMERING

TENTAMEN. Datorteknik. D1/E1/Mek1/Ö Hjälpmedel: Häfte "ARM-instruktioner", A4-format, 17 sidor. Maxpoäng:

Övningsuppgifterna i kapitel F avser FLIS-processorn, vars instruktioner och motsvarande koder definieras i INSTRUKTIONSLISTA FÖR FLISP.

LABORATION. Datorteknik Y

Avbrottshantering. Övningsuppgifter Lösningsförslag Uppgift (Reservation för diverse fel!)

Institutionen för elektro- och informationsteknologi, LTH

Datorteknik. Föreläsning 5. Realtidssystem och realtidsprogrammering. Institutionen för elektro- och informationsteknologi, LTH.

Övningsuppgifter STYRNING - i Mikrodatorteknik för U2 2010

JOFEN-Prototypes. Målsökande pansarvagn. Projektarbete i Kursen EITA15. Jonatan Claesson, Olle Jonasson, Felix Rödén, Edvin Rossi & Nils Olén

Datorteknik 2 (AVR 2)

Tentamen. TSEA22 Digitalteknik 5 juni, 2015, kl

Bilen som inte kan krocka

Effektpedal för elgitarr

LEU240 Mikrodatorsystem

Lösningar till tentamen i EIT070 Datorteknik

Minnet. Minne. Minns Man Minnet? Aktivera Kursens mål: LV3 Fo7. RAM-minnen: ROM PROM FLASH RWM. Primärminnen Sekundärminne Blockminne. Ext 15.

Programallokering. Programtyper. Att placera program i flashrespektive. Program i FLASH-minne. Program i RAM-minne

Lista på registeruppsättningen i PIC16F877A Datablad TTL-kretsar 74-serien

Beskrivning av porthantering i mikroprocessorn SAM3U som används på vårt labkort SAM3U- EK.

Avbrottshantering. Övningsuppgifter

Polling (cyklisk avfrågning) Avbrott

Programmera i teknik - kreativa projekt med Arduino

Föreläsningsanteckningar till Konstruktionsmetoder

ETSA01 Digitala Projekt (I) VT- 13. Projektarbete AC Handledare Bertil Lindvall

Laboration 5. Temperaturmätning med analog givare. Tekniska gränssnitt 7,5 p. Förutsättningar: Uppgift: Temperatur:+22 C

Ett minneselements egenskaper. F10: Minneselement. Latch. SR-latch. Innehåll:

Mål. Datorteknik. Repetition av avbrott. Innehåll. Mätning och styrning. Datorer för mätning och styrning. timer. Datorsystem A/D. Analog insignal D/A

Datorsystemteknik Föreläsning 7DAVA14

Grunderna i stegkodsprogrammering

Mål. Datorteknik. Introduktion. Innehåll. Verklig situation - pappaledighet. Introduktion (forts)

Institutionen för elektro- och informationsteknologi, LTH

Datorteknik. Exempeluppgifter i Laborativ Examination

High Core Remote Car X8000 Cool

CPU. Carry/Borrow IX. Programräknare

Det finns en handledning till kortet på hemsidan. AVR STK500.

F4: Assemblerprogrammering

Tentamen i EIT070 Datorteknik

Övning 6. Parallellport, timer

Övning2 Datorteknik, HH vt12 - Programmering

Självgående fordon Rapport i kursen digitala projekt, EDI021

Digital- och datorteknik

Digital- och datorteknik

F2: Motorola Arkitektur. Assembler vs. Maskinkod Exekvering av instruktioner i Instruktionsformat MOVE instruktionen

Lunds Tekniska Högskola Elektro- och informationsteknik Digitala projekt (EITF11)

Laboration Datorteknik TSIU02 2. I/O-programmering

Datakommunikation med IR-ljus.

Digital- och datorteknik

7) Beskriv tre sätt att överföra parametrar mellan huvudprogram och subrutin.

En något mer detaljerad bild av en processor. De tre delarna i processorn är: Nere 3ll vänster finns e' antal register som används för a' lagra data.

En något mer detaljerad bild av en processor. De tre delarna i processorn är: Nere 3ll vänster finns e' antal register som används för a' lagra data.

Mekanisk solros, Digitala projekt(edi021) Kristoer Nordvall, Stefan Windfeldt, Inlämmnad: 4 december 2006

Datorteknik. Tomas Nordström. Föreläsning 6. För utveckling av verksamhet, produkter och livskvalitet.

Stack och subrutiner Programmeringskonventionen

Tentamen. Datorteknik Y, TSEA28

Tentamen. Datorteknik Y, TSEA28

Tentamen. Datorteknik Y, TSEA28

The Phenomenal Doorbell Bilaga 2. Källkod

Minneselement,. Styrteknik grundkurs. Digitala kursmoment. SR-latch med logiska grindar. Funktionstabell för SR-latchen R S Q Q ?

Styrteknik distans: Minneselement, register, räknare, AD-omv D4:1

Tentamen i Digitala system - EITA15 15hp varav denna tentamen 4,5hp

Grundläggande A/D- och D/A-omvandling. 1 Inledning. 2 Digital/analog(D/A)-omvandling

Digital- och datorteknik

PC-teknik, 5 p LABORATION ASSEMBLERINTRODUKTION

Digitala projekt, EDI021 Rapport Handledare: Bertil Lindvall

Läs igenom hela laboration 5 innan du börjar beskriva instruktionsavkodaren i VHDL!

'HOWHQWDPHQ 6\VWHPNRQVWUXNWLRQ

TSIU50 Mikrodatorprojekt. LAB1 AVR-introduktion och logikanalysator

"Crash Course in Programming"

Mål. Datorteknik. Innehåll. Innehåll (forts) Hur ser ett program ut? Hur skapas maskinkoden?

Övningsuppgifter i Mikrodatorteknik för U2

Exempeluppgift i Logikstyrning. 1 Inledning. 2 Insignaler och utsignaler

EDA480/EDA485 - Maskinorienterad programmering, tentamen 2006-xx-xx 1(7)

Digital- och datorteknik

Datorteknik. Föreläsning 4. Polling och avbrott. Institutionen för elektro- och informationsteknologi, LTH. Mål

/* * dancing3.c * * Created: :53:20 * Author: digpi10 */ #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.

Transkript:

Exempel 4. Användning av en timer Kort beskrivning av Timer/counter1 i ATmega16 Timer/counter1 i ATmega16 består av en 16-bitars räknare och antal register för olika funktioner. Vi skall bara granska hur timern fungerar i output compare mode, d.v.s. då innehållet i räknaren jämförs med innehållet i ett tidkonstantregister. I figur 1 visas ett blockschema för timer/counter1 som beskriver räknaren och jämförelseenheten. Figur 1. Timer/counter med output compare unit. Timer/counter1 är alltså en 16-bitars binärräknare, TNCT1, som kan avläsas eller skrivas till i form av två 8-bitars I/O-register, TCNT1H och TCNT1L. Skrivning och läsning måste utföras som två operationer vilket kan leda till fel då alla bitar inte uppdateras samtidigt. Därför överförs den högre byten först till ett temporärt register, TEMP. Då man vill skriva in ett nytt värde till TCNT1 måste den högre byten TCNT1H skrivas först. Data mellanlagras då i TEMP. Då man skriver den lägre byten överförs den högre byten från TEMP samtidigt som den lägre byten skrivs in till TCNT1L. Då räknaren avläses skall den lägre byten avläsas först. Den högre byten överförs samtidigt till TEMP. Det finns två 16-bitars tidkonstantregister som används vid jämförelse av värdet i räknaren, nämligen OCR1A och OCR1B. I blockschemat har bara ett register ritats ut, OCR1x. Skrivning och avläsning av dessa register sker även via två 8 bitars register OCR1xH och OCR1xL. Här måste också den högre byten skrivas först. Det finns två styrregister, TCCR1A och TCCR1B, med vars hjälp timer/counter1 kan programmeras upp för olika funktioner. TIMSK är ett maskeringsregister för de avbrott som kan utnyttjas för timern. TFIR är ett flaggregister där vissa bitar sätts vid olika händelser. Har man valt output compare mode kan man få ett avbrott (TIMER1 COMPx) då innehållet i räknaren är lika med innehållet i OCR1x. Samtidigt sätts en bit i TFIR. Det går även att sätta eller nollställa en bit på ett anslutningsstift (OC1x) via en vågformsgenerator. Utsignalen till stiftet kan även väljas som en PWM-signal (pulsbreddmodelerad signal). Vi går inte närmare in på dessa funktioner. Som insignal till räknaren kan man använda en yttre klocksignal eller I/O-klocksignalen från processorn. Den senare signalen kan ledas via en frekvensdelare (prescaler) som tar ned frekvensen med en faktor N. Värdet på N kan väljas med hjälp av tre bitar i styrregistret TCCR1B. För frekvensen på klocksignalen till räknaren, f T1, gäller

2 f = T1 N (1) Om innehållet i tidkonstantregistret betecknas T blir tiden t som det tar för TCNT1 att räkna från noll till T t = T (2) f T1 Styrregistren i timer/counter1 Timer/couner1 programmeras upp med de två styrregistren TCCR1A och TCCR1B. Figur 2. Styrregistret TCCR1A. Bitarna 6 och 7 bestämmer funktionssätt för utsignalen OC1A och bitarna 4 och 5 för utsignalen OC1B enligt följande: COM1A1/COM1B1 COM1A0/COM1B0 Beskrivning 0 0 OC1A/OC1B bortkopplade (inte i användning) 0 1 Byt tillstånd på OC1A/OC1B vid jämförelseträff 1 0 Sätt OC1A/OC1B låg vid jämförelseträff 1 1 Sätt OC1A/OC1B hög vid jämförelseträff Skrivs bitarna 2 och 3 (FOC1A och FOC1B) höga tvingas räknaren i ett tillstånd som motsvarar jämförelseträff (compare match) utan att innehållet i räknaren skulle förutsätta detta. Inget avbrott genereras dock. Bitarna WGM11 och WGM10 bestämmer operationsmetod för räknaren tillsammans med bitarna WGM13 och WGM12 i TCCR1B. De flesta av dessa 16 kombinationer har att göra med PWMfunktionerna och beskrivs inte här. Metod WGM13 WGM12 WGM11 WGM10 Beskrivning Toppvärde 0 0 0 0 0 Normal räknare 0xFFFF 4 0 1 0 0 CTC (Clear Timer on Compare match) OCR1A Vid metod 0 fungerar timer/counter1 som en normal räknare som räknar upp tills värdet blir 0xFFFF. Därefter nollas räknaren. Genom att skriva in ett värde i räknaren varje gång som den flödar över kan räkneperioden bestämmas mellan och 0xFFFF. Ett avbrott kan genereras då räknaren flödar över. Vid metod 4 jämförs innehållet i OCR1A (OCR1B kan inte användas). Då räknarens värde är lika med OCR1A nollas räknaren. Ett avbrott kan då genereras.

Bitarna i styrregister TCCR1A visas i figur 3. De två högsta bitarna har att göra med fångstregistret, som inte behandlats här. WGM13 och WGM12 är de två första bitarna i föregående tabell. Det tre lägsta bitarna CS12, CS11 och CS10 bestämmer insignalen till räknaren. 3 Figur 3. Styrregistret TCCR1B Följande tabell anger hur klocksignalen väljs. N är nedskalningsfaktorn från frekvensdelaren. CS12 CS11 CS10 Beskrivning 0 0 0 Timern stoppad 0 0 1 N = 1 (CLK-I/O direkt) 0 1 0 N = 8 (från frekvensdelaren) 0 1 1 N = 64 (från frekvensdelaren) 1 0 0 N = 256 (från frekvensdelaren) 1 0 1 N = 1024 (från frekvensdelaren) 1 1 0 Yttre klocksignal från T1-stiftet. Räknar på fallande kant 1 1 1 Yttre klocksignal från T1-stiftet. Räknar på stigande kant Maskeringsregistret TIMSK innehåller bitar för påkoppling av avbrott från timer/counter1, se figur 4. Figur 4. Maskeringsregistret TIMSK. TICIE1: Avbrott vid fångstoperation om biten 1. OCIE1A: Avbrott vid jämförelseträff med OCR1A om biten 1. OCIE1B: Avbrott vid jämförelseträff med OCR1B om biten 1. TOIE1: Avbrott då räknaren flödar över om biten 1. Flaggregistret TIFR innehåller bitar som sätts då något av de fyra ovanstående tillstånden inträffar, se figur 5. Figur 5. Flaggregistret TIFR.

4 ICF1: Biten sätts vid en fångstoperation. OCF1A: Biten sätts vid jämförelseträff med OCR1A. OCF1B: Biten sätts vid jämförelseträff med OCR1B. TOV1: Biten sätts då räknaren flödar över. Bitarna nollställs automatiskt när servicerutinen för avbrott utförs. Om inte avbrott används kan bitarna nollställas genom att skriva in en etta på bitens plats i TIFR. De bitar som inte visas i TIMSK och TIFR har med de timer0 och timer2 att göra. Uppgiften Gör en assemblerutin för väldefinierade väntetider som kan väljas mellan 0,1 s och 25 s. Gör även ett testprogram som med PB0 i PORTB signalerar SOS med Morse-kod. Tiderna för hög/låg på PB0 definieras i programminnet som en lista med ett direktiv för definiering av konstanter. Systemets klockfrekvens antas vara 4 MHz. Vänterutinerna WaitT Vi kan göra en vänterutin för valbara väntetider på följande sätt. Vi programmerar upp Timer/counter1 så att den fungerar enligt metod 4 (Clear Timer on Compare match). Vi sätter in en sådan tidkonstant i OCR1A at vi får avbrott med intervallen 0,1 s. I ett generellt register har vi en annan tidkonstant ( ett heltal med enheten 0,1 s) som minskas med ett varje gång som timern gör avbrott. Då innehållet i registret blir noll har väntetiden förflutit. Vi bestämmer först faktorn N för frekvensdelaren och tidkonstanten som skall sättas in i OCR1A med hjälp av formlerna (1) och (2). Maximalt värde vi kan sätta in i OCR1A är T max = 2 16 1. Kombinerar vi (1) och (2) och löser ut N får vi det minsta värde N kan ha. Med ett lägre värde kommer vi inte upp till 0,1 s. t 4 10 s 0,1s N min = = = = 6,1 f 16 T1 Tmax 2 1 N kan väljas 1, 8, 64, 256 eller 1024. Vi väljer N = 8. Vi löser ut tidkonstanten T. Med N = 8 får vi 6 t 4 10 s 0,1s 4 T = = = 5 10 N 8 Vi skall nu programmerar upp Timer/counter1. Vi börjat med styrregistret TCCR1A. Vi vill inte påverka några utsignaler, därför skall de 4 högsta bitarna vara nollor. För metod 4 skall vi välja WGM11 = WGM10 = 0. Vidare sätter vi FOC1A = FOC1B = 0, d.v.s. TCCR1A = 0b00000000 I TCCR1B sätts de tre högsta bitarna noll. För metod 4 skall WGM13 = 0 och WGM12 = 1. För att få N = 8 i frekvensdelaren sätts CS12 = 0, CS11 = 1 och CS10 = 0. Vi får -1 6-1 TCCR1B = 0b00001010 I OCR1A skall vi sätta tidkonstanten T :s värde 50000 1 = 49999 för räknaren räknar från 0, inte från 1! OCR1A = 49999 Observera att OCIE1A är ett registerpar vars högre byte måste skrivas in före den lägre byten!

Sedan skall vi koppla på avbrottet för TIMER1 COMPA i registret TIMSK. Biten som skall sättas ett är OCIE1A (bit 4). Då inga andra avbrott från timers behövs blir TIMSK = 0b00010000 = 1<< OCIE1A I stället för att checka att OCIE1A finns i bit fyra och sätta denna bit, kan vi i assemblerprogrammet använda ett uttryck där en etta skiftas OCIE1A steg åt vänster. Biten OCIE1A definieras som 4 i inlclude-filen m16def.inc. Till sist kopplar vi på avbrotten globalt med instruktionen SEI. För att få väntetider mellan 0,1 och 25 sekunder kan vi använda ett 8-bitars generellt register som minskas med ett varje gång timern gör avbrott. Vi kallar detta register Delay. I avbrottsrutinen, Timer1Int, minskar vi Delay med ett såvida detta register inte redan är noll. Adressen till avbrottsvektorn för TIMER1 COMPA är 0x000C. Här sätter vi in instruktionen Jmp Timer1Int Vi gör även en subrutiner i vilka programmet väntar tills väntetiden har förflutit. Vi kallar denna rutin WaitT. Förrän vi kallar på denna rutin borde vi ladda väntetiden (ett heltal med enheten 0,1 s) i. Delay. Programmet skall sedan snurra i en slinga tills Delay. Här kan vi få ett fel mellan 0 och 0,1 s beroende på vilket värde som räknaren TCNT1 råkar ha. Nollar vi TCNT1 i början av rutinerna borde vi komma i från detta fel, men om timern har gjort ett avbrott just före nollningen har kanske Delay redan minskats med ett och det blir ändå ett fel. Där för laddar vi inte in väntetiden i Delay före anropet utan i ett annat register TempT. Innehållet i detta register överförs sedan till Delay efter det TCNT1 nollats i vänterutinerna. 5 Huvudprogrammet Först initieras stackpekaren. Sedan programmeras Timer/counter1 upp enligt ovanstående riktlinjer och biten PB0 väljs som utgång. Denna bit skall sättas och nollställas enligt ett tidschema som sätts in i form av konstanter i programminnet med ett DB-direktiv. Dessa väntetider placeras i minnet f.o.m. adressen 0x002A och adressetiketten Tcode pekar på de två första byten. Tidschemat avslutas med en nolla. Programmet skall nolla PB0 och sedan hämta den första väntetiden från programminnet. Tiden sätts in i TempT och rutinen WaitT anropas. Då väntetiden är slut skall PB0 sättas = 1 och följande tid hämtas o.s.v. (En LED i utvecklingskortet STK500 är kopplad så att den lyser då utsignalbiten är låg) Vi kan hämta väntetiderna från programminnet med hjälp LPM-instruktionen och indirektadressering med postinkrement. Då utnyttjas dubbelregistret Z som adressregister. Registret måste först initieras med adressen till den första väntetiden. Här bör vi observera att adressetiketten Tcode motsvarar en adress till ett ordorganiserat minne (16 bitar/ord), men vi behöver ha en byteadress. Därför måste vi multiplicera adressen med två, d.v.s. skifta bitarna i adressen ett steg till vänster. Initieringen av Z, som måste göras i två steg blir ldi ZL, LOW(Tcode<<1) Kommentar ldi ZH, HIGH(Tcode<<1) I detta exempelprogram finns det inte behov av att göra något under väntetiden, men om det finns kan man inkludera detta i vänteslingorna. Många extra instruktioner i vänteslingorna medför dock att väntetiderna blir mindre exakta. I ett system där vi måste utföra flera uppgifter parallellt är det bättre att konstruera ett enkelt realtidsoperativsystem, där de olika uppgifterna utförs som skilda processer (trådar). Vi kunde även använda Timer/counter1 direkt utan subrutinen WaitT. För varje ny väntetid beräknar vi värdet på tidkonstanten T och sätter in den i timerns register OCR1A. Om vi väljer N = 1024 blir den maximala väntetiden 16 s.

6 Assemblerprogrammet ;==================================================================== ; Exempel på en vänterutin som utnytjar avbrott från Timer1 ; Ett exempelprogram som matar ut SOS i Morse-kod på PB0 ;====================================================================.include "m16def.inc".equ TIMECONST = 49999 ;Definition av register.def FlagSave = r12.def Delay = r13.def Temp = r16.def TempT = r18 ;Tidkonstant för timer1 ;49999 ger avbrott var 0,1:te s ;Register för flaggor vid avbrott ;Kort fördröjningsräknare ;Temporärt register ;Temporärt register för tidkonstant ;Avbrottsvektorer.cseg.org 0x0000 jmp Reset.org 0x000C jmp Timer1Int ;Morsekoden som tider med enheten 0,1 s.org 0x002A Tcode:.db 1, 9, 1, 9, 1, 12, 6, 4, 6, 4, 6, 12, 1, 9, 1, 9, 1, 30,0,0 ;--------------------------------------------------------------------- ; Avbrottsservicerutin för "Timer1 compare match on OCR1A" ; Minskar värdet i fördröjningsräknarna Delay om värdet i detta ; register är olika noll. ;--------------------------------------------------------------------- Timer1Int: in FlagSave, SREG ;Spara statusregistret i FlagSave tst Delay ;= 0? breq ExInt dec Delay ;Minska räknaren Delay med 1 ExInt: out SREG, FlagSave ;Återställ statusregistret reti ;Retur från avbrott ;-------------------------------------------------------------------- ; WaitT, vänterutin med en 8-bitars fördröjningsräknare. ; Upplösningen 0,1 s och maximal väntetid 25,5 s. Anropas med ; väntetiden i TempT med enheten 0,1 s ;-------------------------------------------------------------------- WaitT: clr Temp out TCNT1H, Temp out TCNT1L, Temp ;Synkronisera (nolla Timer1) mov Delay, TempT ;Ladda räknarregistret med tiden Test: tst Delay ;Delay = 0? brne Test ;Vänta tills Delay = 0 ret ;----------------------------------------------------------------------

7 ; Reset, huvudprogrammet startar här med att initiera stackpekaren och ; programera upp Timer1 i CTC-mod med avbrott. Biten PB0 sätts = 0, ; en väntetid hämtas från Tcode, programmet väntar i WaitT, sedan ; sätts PB0 = 1. Detta schema upprepas tills väntetiden 0 hämtas. Då ; startas schemat igen från början av Tcode. ;---------------------------------------------------------------------- Reset: ldi Temp, LOW(RAMEND) ;Initiera stackpekaren out SPL, Temp ldi Temp, HIGH(RAMEND) out SPH, Temp clr Temp ;Nolla temp out TCCR1A, Temp ;OC1A, OC1B frånkopplade ldi Temp, 0b00001010 ;Nolla T1 då T1= OCR1A, K = 8 out TCCR1B, Temp ;CTC mod ldi Temp,HIGH(TIMECONST) out OCR1AH, Temp ;Högre byten först till OCR1A!! ldi Temp,LOW(TIMECONST) out OCR1AL, Temp ;Lägre byten sedan till OCR1A ldi Temp, (1<<OCIE1A) ;Skifta 1 till OCIE1A:s plats out TIMSK, Temp ;Avbrott då TCNT1 = OCR1A ldi Temp,0b00000001 out DDRB, Temp ;PB0 utgång clr Delay ;Nolla fördröjningsräknaren sei ;Koppla på avbrotten globalt Restart: ldi ZL, LOW(Tcode<<1) ;Ordadress till byteadress med skift ldi ZH, High(Tcode<<1) ;Z pekar på först kodbyten Loop: cbi PORTB, 0 ;Nollställ PAB0 i port B lpm TempT, Z+ ;Hämta en kodbyte tst TempT ;= 0? breq Restart ;Starta på nytt från början rcall WaitT ;Vänta så lång tid som anges i koden sbi PORTB, 0 ;Sätt PB0 lpm TempT,Z+ ;Hämta följande kodbyte tst TempT ;= 0? breq Restart ;Starta om från början av koden rcall WaitT ;Vänta så lång tid som anges i koden rjmp Loop ;Fortsätt med nästa varv ;----------------------------------------------------------------------