Side 1 af 13 Dato: 03-06-03 Til Sigurd Som aftalt får du nu tilbygningen til 80C535 kittet, keyboard og programmet med programopdatering. Den sidste opgave her, gik så ud på at tilslutte et tastatur, og lave programtilføjning, sådan at når der trykkes på tast 1, kommer der et 1-tal på displayet, og når der tast 2, kommer der et 2-tal på displayet, osv. op til F. I starten virkede det som en overkommelig opgave, men det skulle vise sig at være noget sværere end forventet, så det er også derfor at du ikke får et program der virker fuldt ud. Det der ikke virker er, at får alle tastetryk på displayet, vi kan godt få noget ud på displayet, bare ikke det rigtige og ikke alle taster giver noget ud på displayet, men alt hardware er testet igennem og virker, så det er det rent programmeringsmæssige, der gør at det ikke virker helt. Men undervejs i gennemgangen af programmet vil jeg komme ind på hvor det er det er galt, sådan at du selv kan gøre det færdig. Men her først lidt om hvordan det er bygget op hardware og softwaremæssigt. Først er her displayet med de 16 taster, 0 9 og A F. Herunder vises hvordan det ser ud: Og her vises forbindrne (set fra bagsiden): Som det ses er der 8 tilslutningsben, og det virker ved at, Y1-4 er brugt som indgang/indlæsning, og X1-4 er udgange/aflæsning, derudover har vi valgt at bruge pullup-modstande, 4 stk. på 10,7 ko, på udgangene, sådan at signalet fra dem altid er trykket højt, indtil der trykkes på en tast, så bliver den lav. Så er fidusen så at man i programmet sender en test-funktion på Y1-4:
Side 2 af 13 Dato: 03-06-03 char test_key() char var; wr_key(0x0f); var=rd_key(); if(var==0xf0)return 0; return 1; (Hele programmet vil komme i sin helhed til sidst). // funktion til at sende test-mønster til keyboard I denne funktion sættes alle indgange på keyboardet høje, og så aflæses der på udgangssignalet Y1-4 + X1-4 og hvis det er forskelligt fra FF H så ved programmet at der er trykket på en tast. Men hvis der ikke er det fortsætter programmet bare med at gøre det, som det ellers er i gang med. Men er der trykket på en tast, så skal programmet fortsætte ind i en funktion for at finde ud af hvilken tast det er der er trykket på. Af læsning af hvilken tast der trykket på, er lavet på denne måde: Inde under knapperne er der nogle kontakter der skal have forbind, for at der kan aflæses det signal vi skal bruge: Og for at få et resultat ud man kan bruge til noget ligge man X og Y sammen, så hvis der f.eks. er trykket på tast 5, resultatet af det signal, i binær, blive 1011 1011 B, men da udstyret kun kan læse hex, ser det sådan ud 4B H. Det gøres ved at, når test-funktionen finder ud af at der er trykket, kører den en funktion hvor den finder ud af hvilken tast det er, og det gør den ved, først at sende et bit mønster som det her 1110 til Y1-4 og så aflæser den på X1-4 om der er et signal der er blevet lavt, og er der ikke det, sender den signalet 1101 og så aflæses igen på X1-4, og her er der så trykket tast 5, og så er der jo en aflæsning der ser sådan 1011. I alt bliver lavet fire test/indlæsninger og fire aflæsninger, i alt 16 taster. Det er denne funktion vi ikke har fået til at virke. Så der kommer desværre ikke noget brugbart signal fra keyboard til display. Når tasten der trykket på, er fundet, afbrydes det der ellers sker på displayet/kittet, og karakteren sendes til displayet. Som det ses til sidst, er der en last_key og det er for at, hvis nu det viser sig at der slet ikke var trykket på en knap alligevel, og der har været en fejl aflæsning, vil funktionen sende et Y til displayet. Her ses også test_key funktionen, som tidligere omtalt, først. Funktionen ser sådan ud:
Side 3 af 13 Dato: 03-06-03 if(test_key()) wr_key(0x0e); wr_key(0x0d); wr_key(0x0b); wr_key(0x07); last_key='y'; // Tester om der er trykket på en tast // Hvis der er en fejl skrives et Y på displayet Som det ses her i aflæsningsfunktionen, er der en wr_key og en rd_key, det er en write data key og read data key, wr_key sender en bitmønster ind på Y1-4, og rd_key aflæser X1-4, de to funktioner ser sådan ud: void wr_key(char bitmap) keyboard=bitmap; clk_key=1; clk_key=0; char rd_key() char input; keyboard=0xff; oe_key=0; input=keyboard; oe_key=1; return input; // funktion til at skrive til keyboard // funktion til at læse fra keyboard Den sidste nye i programmet er en switch case funktion. Det signal som bliver resultatet af sammenlægningen i sammenlignings-sløjfen (som desværre ikke virker efter hensigten), bliver omsat til en karakter som sendes til displayet. Den er lavet sådan:
Side 4 af 13 Dato: 03-06-03 void dekod (char getchar) // Funktion der dekoder signal fra keyboard. switch (getchar) // Getchar returnerer værdien af den tast der er trykket på case 0xEE: last_key='1'; // Key 1 returnerer værdien 87H case 0xED: last_key='2'; // Key 2 returnerer værdien 67H case 0xEB: last_key='3'; // Key 3 returnerer værdien 27H case 0xE7: last_key='4'; // Key 4 returnerer værdien 8BH case 0x6B: last_key='5'; // Key 5 returnerer værdien 6BH case 0x2B: last_key='6'; // Key 6 returnerer værdien 2BH case 0x8D: last_key='7'; // Key 7 returnerer værdien 8DH case 0x6D: last_key='8'; // Key 8 returnerer værdien 6DH case 0x4D: last_key='9'; // Key 9 returnerer værdien 4DH case 0x6E: last_key='0'; // Key 0 returnerer værdien 6EH case 0x8E: last_key='a'; // Key A returnerer værdien 8EH case 0x2E: last_key='b'; // Key B returnerer værdien 2EH case 0x1E: last_key='c'; // Key C returnerer værdien 1EH case 0x1D: last_key='d'; // Key D returnerer værdien 1DH case 0x1B: last_key='e'; // Key E returnerer værdien 1BH case 0x17: last_key='f'; // Key F returnerer værdien 17H default: last_key='k'; // Fejlkode for fejltast med værdien 4BH Her skal tages højde for at, de hex-koder der er sat for at definere de forskellige karakterer ikke er de rigtige da vi ikke har haft mulighed for at teste programmet ordentlig igennem, pga. de problemer der har været der har været med at få keyboardet til at skrive ud til displayet. Vi har valgt at bruge pull-up metoden, hvor man trækker udgangene høje, med modstande, til at trække udgangene høje som default, da processoren nemt kan trække høj, men ikke lav, så undgår man at få fejl i udstyret. Derudover er der monteret 2 latche af typen 74HC/HCT573, én til indgangssignalet af keyboardet, og én til udgangssignalet. De bruges til at gemme signalet der enten er sendt eller aflæst, til og fra keyboardet. En latch er en et bits hukomm, og i latchen er der otte latche, dvs. den kan håndtere 8 bit eller en byte, hvor man kan styre hvornår der skal åbnes for indlæsning og udlæsning af de data der står i dem. Latchen forsynes med en 5V jævnspænding der tilsluttes på Vcc ben nummer 20 og GND på ben nummer 10. Ud over disse ben er der to ben der styrer hvornår der indlæses og udlæses data. Indlæsning bestemmes af det ben der er benævnt LE (Latch enable). Der åbnes for indlæsning af data når LE
Side 5 af 13 Dato: 03-06-03 sættes lav. Når dette er gjort gemmes de værdier der er blevet indlæst i lachen. For at få udlæst data fra lachen skal det ben der hedder OE (Output Enable) sættes høj. Ind og udlæsning sker på ben d0-7 og q0-7. På næste side følger en diagram over hvordan latche og keyboard er forbundet til portene.
Side 6 af 13 Dato: 03-06-03 Herunder vises et diagram over hvordan keyboard er tilsluttet til latch og porte, og hvordan forsyningen er forbundet: Vcc GND P5.5 P5.3 P4.0 P4.1 P4.2 P4.3 P4.4 P4.5 P4.6 P4.7 10,7Kohm 20 1 OE Vcc1 19 q0 2 3 d0 18 q1 17 d1 q2 4 16 d2 q3 5 d3 Latch q4 15 6 1 14 7 d4 P4.0-P4.3 q5 13 d5 q6 12 8 d6 q7 11 9 d7 GND LE 10 20 1 OE Vcc1 19 q0 2 3 d0 18 q1 17 d1 q2 4 16 d2 q3 5 Latch d3 2 q4 15 6 P4.4-P4.7 14 d4 q5 7 13 d5 q6 12 8 d6 q7 11 9 d7 GND LE 10 X1 X2 X3 X4 Y1 Y2 Y3 Y4 1 2 3 F 4 5 6 E 7 8 9 D A 0 B C
Side 7 af 13 Dato: 03-06-03 Herefter følger programmet, det hele inkl. Den gamle del: // Initialiserings-sekvens #pragma model=medium #pragma code=0x0000 #pragma xdata=0x4000 #pragma asm=on #define display P4 #define keyboard P4 //--------------------------------- Definition af porte og funktioner ------------------------- bit RS at P5.0; // Definere bit Data input på port 5.0 bit RW at P5.1; // Definere bit data read (1)/write (0) på port 5.1 bit Enable at P5.2; // Definere bit enable på port 5.2 bit busy_ben at P4.7; // Definere bit busy_ben på port 4.7 bit oe_key at P5.3; // Definere bit oe_key på på port 5.4 bit clk_key at P5.5; // Definere bit clk_key på på port 5.3 void wr_ins(char); void wr_data(char); void clr_scr(char); void cursor (char); void delay (char); void full_scr(); void ini_disp (); void busy_read(); void lcd_dkch(); void dekod (char); void wr_key(char bitmap); char rd_key(); char test_key(); char last_key; char key_used; // Definere funktion skriv instruktion // Definere funktion skriv data // Definere funktion ryd skærm // Definere funktion Sæt cursor et vilkårligt sted // Definere funktion delay // Definere funktion tekststreng // Definere funktion initialisering af display // Definere funktion // Definere funktion lær danske karakterer // Definere funktion "dekod hvilken tast" der er trykket // Definere funktion skriv data på "ind" ben på keyboard // Definere funktion læs data på "ud" ben på keyboard // Definere funktion sender test-data til keyboard, for // at "undersøge" om der er trykket på en tast. // Definering af global variabel, sidste tast. // Definering af variabel, der finder ud af om last_key er i brug, // eller brugt //--------------------------------- Danske karakterer ----------------------------------------- void lcd_dkch(void) // Lær danske karakterer char ch; // char variabel som tæller afsendte pixels const char dk_ch[]= 0x00, 0x0A, 0x00, 0x04, 0x04, 0x11, 0x0E, 0x00, // Hex koder for "smiley" 0x00, 0x00, 0x0E, 0x15, 0x15, 0x12, 0x0D, 0x00, // Hex koder for "æ" 0x00, 0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00, // Hex koder for "ø" 0x04, 0x0A, 0x0E, 0x01, 0x0F, 0x11, 0x0F, 0x00, // Hex koder for "å" 0x07, 0x0C, 0x14, 0x1F, 0x14, 0x14, 0x17, 0x00, // Hex koder for "Æ" 0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E, 0x00, // Hex koder for "Ø" 0x04, 0x0A, 0x15, 0x11, 0x1F, 0x11, 0x11, 0x00, // Hex koder for "Å" 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00 // Hex koder for "gradtegn" ; // definitionen af :-) æ ø å Æ Ø Å "gradtegn". delay(1); wr_ins(0x40); // adresse sættes til start af CG-Ram. delay(400); // vent til færdig. ch = 0; while(ch<=63) // karakter sendes. wr_data(dk_ch[ch]); // Skriver danske karakterer ch++; busy_read(); // pause efter sidste lcd_data. wr_ins(0x80); // curser til første plads. delay(400); //--------------------------------- Main program ---------------------------------------------- void main (void) // Main funktion.
Side 8 af 13 Dato: 03-06-03 ini_disp(); // Initialisere display. lcd_dkch(); // Indlæser danske karakterer. delay(1000); // Pause inden der skrives på display cursor(0); // Placerer cursor på første plads i anden linie full_scr(); // Udfører funktionen full_scr. (skriv tekststreng) while (1) // Uføres så længe der er strøm på. if(test_key()) // Tester om der er trykket på en tast wr_key(0xe0); if(rd_key)dekod(rd_key()+0x0e); wr_key(0x0d); wr_key(0x0b); wr_key(0x07); last_key='y'; wr_data (last_key); // Hvis der er en fejl skrives et Y på displayet //--------------------------------- Skriv instruktion til display ----------------------------- void wr_ins(char karakter) RS=0; RW=0; display=karakter; Enable=0; Enable=1; Enable=0; // Funktion til at skrive instruktioner til display. // Register valg. // Læs/skriv. // Skriver karakter til display. // Sæt enable. // Sæt enable. // Sæt enable. //--------------------------------- Skriv data til display ------------------------------------ void wr_data(char karakter) // Funktion til at skrive data til display. switch (karakter) case 'æ': karakter = 0X01; // Hvis karakteren er æ skriv HEX 0X01. // Hvis æ hop til slut(). case 'ø': karakter = 0X02; // Hvis karakteren er ø skriv HEX 0X02. // Hvis ø hop til slut(). case 'å': karakter = 0X03; // Hvis karakteren er å skriv HEX 0X03. // Hvis å hop til slut(). case 'Æ': karakter = 0X04; // Hvis karakteren er Æ skriv HEX 0X04. // Hvis Æ hop til slut(). case 'Ø': karakter = 0X05; // Hvis karakteren er Ø skriv HEX 0X05. // Hvis Ø hop til slut(). case 'Å': karakter = 0X06; // Hvis karakteren er Å skriv HEX 0X06. // Hvis Å hop til slut(). default: ; // Hvis karakteren ikke står ovenfor karakter = karakter. RS=1; // Register valg. RW=0; // Læs/skriv. display=karakter; // Skriver karakter til display. Enable=0; // Sæt enable. Enable=1; // Sæt enable. Enable=0; // Sæt enable. delay (1000); // Pause inden næste bogstav.
Side 9 af 13 Dato: 03-06-03 //--------------------------------- Slet skærm ------------------------------------------------ void clr_scr (void) //Sletning af display og curser til start af skærm. char space; // Tildeler variablen space værdien af en char. for (space=0;space<40;space++) wr_ins (0X80+space); delay (1000); wr_data (' '); for (space=0;space<40;space++) wr_ins (0XC0+space); delay (1000); wr_data (' '); wr_ins (0X80); //--------------------------------- Sæt cursor et vilkårligt sted på display ------------------ void cursor (char ch) // Denne funktion sætter curser på en vilkårlig plads på // displayet. Plads 0-40 er første linie char tal; // og plads 40-80 på den anden. if (ch<40) tal=0x80+ch; wr_ins (tal); tal=0xc0+ch-40; wr_ins (tal); //--------------------------------- Pause tid ------------------------------------------------- char delay(char tid) // Funktion Delay unsigned int taller; // Tildeler variablen taller værdien af en unsigned int for (taller=0; taller <tid; taller++); // Længde på pause //--------------------------------- Tekststreng ----------------------------------------------- void full_scr (void) // Funktion til at skrive en tekststreng. const char besked[] = "Dette er noget lort, som IKKE virker!!!"; // Her skrives en tekst. char ch=0; // Tildeler variablen ch værdien af en char. while (ch<=39) // Her skrives linie længde. wr_data(besked[ch]); // Skriver besked til display. ch++; // Flytter til næste plads efter hver karakter. //--------------------------------- Initialisering af disply ---------------------------------- void ini_disp() delay (65000); delay (65000); delay (20000); wr_ins (0X38); delay (41000); wr_ins (0X38); delay (1000); wr_ins (0x38); delay (400); wr_ins (0x38); delay (400); wr_ins (0x06); // Initialisering af display.
Side 10 af 13 Dato: 03-06-03 delay (400); wr_ins (0x0F); delay (400); wr_ins (0x01); delay (16400); wr_ins (0x80); delay (400); //--------------------------------- Aflæser om der er kommunikation --------------------------- void busy_read() display = (0xFF); RS = 0; RW = 1; Enable = 1; while (busy_ben); Enable = 0; // Aflæser om der sendes til display. // port gøres klar til indlæsning // kontrolben stilles ind // kontrolben stilles ind // kontrolben stilles ind // busy_ben aflæses kontinuert // aflæsning slut, enable sættes lav //--------------------------------- Keyboard funktion ----------------------------------------- void dekod (char getchar) // Funktion der dekoder signal fra keyboard. switch (getchar) // Getchar returnerer værdien af den tast der er trykket på case 0xEE: last_key='1'; // Key 1 returnerer værdien 87H case 0xED: last_key='2'; // Key 2 returnerer værdien 67H case 0xEB: last_key='3'; // Key 3 returnerer værdien 27H case 0xE7: last_key='4'; // Key 4 returnerer værdien 8BH case 0x6B: last_key='5'; // Key 5 returnerer værdien 6BH case 0x2B: last_key='6'; // Key 6 returnerer værdien 2BH case 0x8D: last_key='7'; // Key 7 returnerer værdien 8DH case 0x6D: last_key='8'; // Key 8 returnerer værdien 6DH case 0x4D: last_key='9'; // Key 9 returnerer værdien 4DH case 0x6E: last_key='0'; // Key 0 returnerer værdien 6EH case 0x8E: last_key='a'; // Key A returnerer værdien 8EH case 0x2E: last_key='b'; // Key B returnerer værdien 2EH case 0x1E: last_key='c'; // Key C returnerer værdien 1EH case 0x1D: last_key='d'; // Key D returnerer værdien 1DH case 0x1B: last_key='e'; // Key E returnerer værdien 1BH case 0x17: last_key='f'; // Key F returnerer værdien 17H default: last_key='k'; // Fejlkode for fejltast med værdien 4BH //--------------------------------- Skriv til keyboard ----------------------------------------- void wr_key(char bitmap) keyboard=bitmap; clk_key=1; clk_key=0; // funktion til at skrive til keyboard //--------------------------------- Læs fra keyboard ------------------------------------------- char rd_key() char input; // funktion til at læse fra keyboard
Side 11 af 13 Dato: 03-06-03 oe_key=0; input=keyboard; oe_key=1; return input; //--------------------------------- Test keyboard ---------------------------------------------- char test_key() char var; wr_key(0x0f); var=rd_key(); if(var==0xf0)return 0; return 1; // funktion til at sende test-mønster til keyboard
Side 12 af 13 Dato: 03-06-03 Her til sidst vil jeg lige lave en konklusion over dette projekt. Da vi ikke har fået det til at virke helt, er det selvfølgelig ikke en tilfreds føl man har når man afleverer det, men der udover må jeg sige at jeg har lært noget om fejlfinding i sådan et program, bl.a. at hvis man skal teste et signal kan man sætte en while (1); ind, for så får man programmet til at stoppe lige hvor man gerne vil, endvidere kan man, hvis man f.eks. vil tjekke om man kan styre en ports høje og/eller lave signal, sætte denne kode ind: P5.5 = 0 While (1); Så stopper programmet lige efter (1); og man kan så måle på port 5.5 og se om den faktisk er lav, som man har bedt om, og man kan også sætte den til P5.5 = 1, og så teste den om den faktisk er høj. Men udover det har jeg også fundet ud af, man skal være meget opmærksom på hvad man laver når man programmerer, det kan så nemt gå i den gale retning, som det er gået her, måske ikke så galt som det kunne have gået, for jeg har en fornemm af at vi er tæt på det rigtige resultat. Men alt i alt et spændene projekt. Og så vil jeg da lige her til sidst komme med en rett til det sidste program, hvor jeg skrev til dig at der hvor der stod at de delays var defineret i µs, det er en fejl, for at få den rigtige tid, bliver man nød til at have kittet målt med et oscilloscop, for tiden er noget længere for en instruktion end vi lige havde regnet med. Så har jeg, her på sidste side, sat et billede ind af hele kittet, med keyboard, display.
Side 13 af 13 Dato: 03-06-03