Lab 10
Lab 10
Lab 10
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Namn:<br />
<strong>Lab</strong>orationen godkänd:<br />
<strong>Lab</strong>oration <strong>10</strong><br />
Digitala system <strong>10</strong> p<br />
LTH Ingenjörshögskolan vid Campus Helsingborg<br />
Datorteknik, laboration 3.<br />
Avbrottshantering, klocka.<br />
Schemat från föregående laboration<br />
är nu kompletterat med två anslutningar<br />
till displayen.<br />
LE (Latch Enable)<br />
Om LE dvs bit 7 i PORTC sätts = 0,<br />
så är D1 och D2 öppna för data från<br />
PORTB.<br />
BL (Blanking)<br />
Om BL (Blanking) dvs bit 3 i PORTA<br />
sätts = 1, så släcks displayen.<br />
I nästan alla konstruktioner med enchipsdatorer låter man vissa programavsnitt köras<br />
med regelbundet återkommande intervall. Ibland behöver man göra regelbundna<br />
avläsningar av givare eller ha en exakt tidbas för en klocka. I denna laboration<br />
ska vi se hur man använder ett periodiskt avbrott. Vi ska använda alla fyra siffrorna i<br />
displayen för att göra en klocka med hjälp av det interna avbrottet OC2.<br />
Förberedelser:<br />
Läs i kompendiet kap 4 (Avbrottshantering) och 5.4 (Output Compare).<br />
Använd också databoken kap 5.4 och 9.3.<br />
Till laborationen måste du bl.a. känna till följande begrepp:<br />
Avbrottsvektor, avbrottsrutin, lokal avbrottsmask, kvittering av avbrott.<br />
Stefan Nyman 2006-02-03
Förbered laborationsuppgifterna 2, 4 och 5.<br />
Med hjälp av tipsen du får på föreläsningarna, kan göra det mesta före laborationen.<br />
Hemuppgift:<br />
Skriv en funktion countSeconds som utför följande:<br />
1. Öka variabeln seconds med ett.<br />
2. Justera värdet så att det ser decimalt ut.<br />
3. Nollställ det om det skulle bli = 60.<br />
4. Returnera värdet som ändrats så man lätt kan testa om det blivit = 0.<br />
Här är skalet till funktionen countSeconds.<br />
char countSeconds()<br />
{<br />
; // Öka variabeln seconds<br />
; // Decimaljustering<br />
; // Nollställ om det blivit 60 60<br />
return seconds;<br />
}<br />
<strong>Lab</strong>orationsuppgifter:<br />
<strong>Lab</strong>orationens mål är att få displayen att visa timmar och minuter<br />
eller minuter och sekunder.<br />
Klockan ska styras med timeravbrottet OC2, som ska ge avbrott var <strong>10</strong>:e ms utan att<br />
påverka någon utgång.<br />
Den ska kunna ställas genom att man trycker på knapparna:<br />
• Klockan går normalt om ingen knapp trycks ner<br />
• Klockans timmar bläddras upp med hjälp av en knapp.<br />
• Klockans minuter bläddras upp med en annan knapp.<br />
2<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
Uppgift 1.<br />
Skapa ett nytt projekt Klocka.prj. Utgå från inställningarna i <strong>Lab</strong>3.prj så slipper du<br />
göra om dom.<br />
Projektet ska innehålla:<br />
‣ cstartup.s07<br />
‣ Clock.c<br />
Uppgift 2.<br />
Denna fil skriver du i denna laboration. Enklast tar du den<br />
föregående laborationens Logik.c och kopierar och döper om<br />
den. Spara funktionerna initL1 och main. De andra funktionerna<br />
kan du ta bort!<br />
<br />
Funktioner för att initiera och sköta avbrott med periodiskt intervall. Avbrottet<br />
OC2 ska startas och styras så att det kommer exakt var <strong>10</strong>:e ms.<br />
Funktionen initOC2 ska innehålla de programrader som initierar OC2 så att det<br />
genereras avbrott utan att påverka någon utgång.<br />
Fyll först i hur dessa två register ska programmeras:<br />
TCTL1<br />
TMSK1<br />
Skriv funktionen!<br />
Avbrottsfunktionen OC2_interrupt skrivs nästan som en vanlig funktion.<br />
Definitionen måste föregås av ordet ”interrupt” och funktionens namn måste vara<br />
exakt det som återfinns i Vectors.h<br />
Avbrottsflaggan måste kvitteras och tiden för nästa Output Compare laddas i<br />
TOC2. Skriv en avbrottsfunktion som sköter dessa saker, dvs gör så att OC2 inträffar<br />
exakt var <strong>10</strong>:e ms.<br />
TFLG1<br />
TOC2 Decimalt: ..............<br />
Observera att du inte kan skriva samma värde i OC2 varje gång, utan egentligen ska<br />
skriva in den tidpunkt då nästa avbrott ska ske.<br />
3<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
Här är skalet till dessa två funktioner:<br />
// OC2 ska ge avbrott utan att påverka några utgångar.<br />
void initOC2 (void)<br />
{<br />
;<br />
}<br />
// Avbrottsfunktion OC2 kommer var <strong>10</strong>:e ms.<br />
interrupt void OC2_interrupt(void)<br />
{<br />
; // Kvittera avbrottet<br />
; // Återladda TOC2<br />
}<br />
<br />
Uppgift 3.<br />
Genom att skriva ett minimalt huvudprogram, kan du testa att avbrottet fungerar.<br />
Initiering<br />
initL1<br />
initOC2<br />
Huvudprogram<br />
OC2_interrupt<br />
Här har du hela skalet till Clock.c.<br />
// Clock.c<br />
#include "IO-reg.h" // Definitioner av alla registeradresser.<br />
#include "Vectors.h" // Ser till att avbrottsvektorer initieras.<br />
#include "intr6811.h" // Deklarationer av specialare, t.ex.<br />
// enable_interrupt().<br />
// Funktionerna: initL1, initOC2 och OC2_interrupt skriver du här.<br />
main(void)<br />
{<br />
initL1();<br />
initOC2();<br />
enable_interrupt();<br />
while (1)<br />
{<br />
}<br />
}<br />
4<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
Det kan vara svårt att testa att avbrottet kommer med exakt <strong>10</strong> ms intervall, men<br />
man kan ändå se att det kommer ofta. Lägg t.ex till raden<br />
PORTB++;<br />
i avbrottsfunktionen.<br />
Uppgift 4.<br />
I avbrottsfunktionen ska nu en klocka räkna upp displayen med sekunder och minuter.<br />
Avbrottsfunktionen för OC2 körs ju nu automatiskt var <strong>10</strong>:e ms. Skriv en<br />
funktion, clock(), som gör följande:<br />
<br />
clock<br />
Öka räknare med 1<br />
= <strong>10</strong>0 <br />
Ja<br />
Nollställ<br />
räknaren<br />
countSeconds<br />
Nej<br />
= 0 <br />
Ja<br />
countMinutes<br />
Nej<br />
= 0 <br />
Ja<br />
countHours<br />
Nej<br />
newtime = 1<br />
klart<br />
Härovan har du clock i form av flödesplan.<br />
Funktionen clock ska anropas från avbrottsrutinen som kommer var <strong>10</strong>.e ms och<br />
räkna upp variablerna counter, seconds, minutes och hours enligt flödesplanen ovan.<br />
Dessutom ska en variabel newtime användas som flagga att klockan ändrat värde.<br />
Variablerna ska fungera såhär:<br />
• counter: En räknare som räknar <strong>10</strong>0 avbrott. När counter = <strong>10</strong>0 ska den nollställas<br />
och sekunderna ska räknas upp.<br />
5<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
• seconds: Räknas upp med ett och decimaljusteras varje gång. Om sekunderna<br />
fått värdet 60 (efter decimaljustering) ska de nollställas och minuterna ska räknas<br />
upp.<br />
• minutes: Räknas upp och nollställs på samma sätt som sekunderna.<br />
• newtime: Ettställs varje gång klockan ändrat värde.<br />
clock använder funktionerna countSeconds, countMinutes och countHours som<br />
var och en returnerar värdet 0 om resp. räknevärde blivit = 0.<br />
Försök att själv komma på hur decimaljustering ska kunna göras.<br />
Testa programmet!<br />
Hitta själv på hur du ska sätta brytpunkter för att konstatera att programmet går<br />
rätt. Passa också på att titta på variablerna seconds och minutes t.ex.<br />
<br />
Uppgift 5.<br />
Vi ska komplettera med en funktion display som ska skriva ut innehållet i en 16-<br />
bitarsvariabel till displayen.<br />
// display<br />
// Skriver ut värdet av en 16-bitarsvariabel på displayen.<br />
void display(int siffror) // Funktionens lokala variabel: siffror<br />
{<br />
; // Nollställ stroben<br />
; // Skriv höga halvan av Siffror till PORTB<br />
; // Ettställ stroben<br />
; // Skriv låga halvan av Siffror till PORTB<br />
}<br />
Funktionen anropas med ett 16-bitarsvärde som parameter.<br />
T.ex. om A och B är två 8-bitarsvariabler så gör anropet<br />
display (A*256 + B);<br />
att värdet av A syns till vänster och B till höger.<br />
<br />
6<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
Uppgift 6.<br />
main<br />
Initieringar<br />
newtime<br />
=0<br />
Ja<br />
Nej<br />
Skriv ut<br />
tiden<br />
newtime = 0<br />
Komplettera nu huvudprogrammet så att det skriver ut minuter och sekunder varje<br />
gång newtime inte är = 0.<br />
Vad händer om man inte testar newtime utan skriver ut hela tiden<br />
....................................................................<br />
Varför......................................................................................................................<br />
Observara att innan du anropar display ska minuter och sekunder kombineras ihop<br />
till en 16-bitarsvariabel.<br />
Efter utskriften nollställs newtime.<br />
Tips: om man vill testa om newtime är skilt från 0, kan man helt enkelt skriva:<br />
if (newtime)<br />
{<br />
;<br />
}<br />
Det ser ju rätt lättläst ut.<br />
<br />
7<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03
Uppgift 7.<br />
Det är bra om klockan kan ställas. Komplettera funktionen clock så att timmar och<br />
minuter kan stegas upp.<br />
Varje sekund testas knapparna:<br />
• Om ingen är nere: normal gång.<br />
• Om en av knapparna är nere (välj själv): Räkna upp timmarna.<br />
• Om en annan är nere: Räkna upp minuterna och nollställ sekunderna.<br />
Om man håller nere en knapp kommer uppräkningen att ske med ett varje sekund.<br />
Om man tycker det går för långsamt, så kan man också passa på att tvångsställa variabeln<br />
counter till ett mindre värde än <strong>10</strong>0.<br />
<br />
I nästa laboration kommer vi att bland annat se hur man på ett bättre sätt kan ställa<br />
klockan. Man vill ju t.ex. bläddra upp tiden med knapparna i sin egen takt.<br />
8<br />
Digitala system , <strong>Lab</strong><strong>10</strong> 2006-02-03