Tyto stránky již nejsou udržovány. Obsah je postupně přesouván/aktualizován na adrese chytrosti.marrek.cz.
1/1
Na této stránce najdete příklady jak v assembleru, tak v jazyce C. Jazyk C se sice na naší škole (stále ještě -- už zase) nevyučuje. Nic ale nebrání vašemu samostudiu.
Jako vývojové prostředí jsem si oblíbil program MCU 8051 IDE. Umí toho pravdu hodně. Neznáte-li -- vyzkoušejte! Pokud nejste závislí na vašem oblíbeném editoru typu Vim nebo Emacs budete jistě spokojeni. Lze jej použít pro přehlednou a pohodlnou práci nebo jen jako překladač nebo ladící nástroj.
Jako překladač jazyka C používám SDCC. V MCU 8051 IDE je integrována podpora pro tento kompilátor, ale kompilátor jako takový si musíte nainstalovat zvlášť.
Následující příklady se opírají o toto zapojení:
Možná se budou hodit i následující odkazy:
Zde si můžete si stáhnou kompletní zdrojové kódy. Pro kompilaci používám program make. Najdete zde tedy i příslušné Makefile.
Abych neustále neopisoval jednu a tu stejnou část kódu používám v některých příkladech knihovny:
Jednoduchý příklad pro blikání led.
Assembler:
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: bli-blik-1.asm
3 ; Datum: 19.12.2011
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: jednoduché blikání
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8
9 start:
10 mov P0,#0F0H ; 4 LED nesvítí, 4 LED svítí
11 call del200m ; čekej 200ms
12 mov P0,#00FH ; 4 LED svítí, 4 LED nesvítí
13 call del800m ; čekej 800ms
14 jmp start ; skok na začátek
15 jmp start
16
17 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18 ; podprogramy pro zpoždění
19 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 del800m: CALL del400m
21 del400m: CALL del200m
22 del200m: ; 200 ms
23 MOV R6, #254d ; 1CS
24 MOV R7, #196d ; 1CS
25 NOP ; 1CS
26 NOP ;1 SC
27 DJNZ R7, $-2 ; 196x4 = 784 SC
28 DJNZ R6, $-6 ; 787x254 = 199898 SC
29 ; chybí ještě 97 SC
30 MOV R7, #48d
31 DJNZ R7, $
32 RET ; 2CS
33
34 END
Céčko:
1 /* Soubor: blik-blik-1.c
2 * Datum: 19.12.2011
3 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
4 * Licence: GNU/GPL
5 * Úloha: jednoduché blikání LED na P0.
6 ****************************************************/
7 #include <at89x52.h>
8
9
10 /** Funkce pro časové zpoždění 10 ms až 2550 ms.
11 * (Pro OSC 12.0 MHz) Časové zpoždění je vždy násobkem 10 ms.
12 * Režije spojená s voláním funkce k zadanému zpoždění
13 * přidává ještě dalších 8 us.
14 *
15 * @param koef Celkové zpoždění = koef x 10ms. */
16 void delay_10m_x(unsigned char koef)
17 {
18 koef; //pouze prázdný výraz, abych nedostával warning při kompilaci
19 __asm
20 MOV R5,DPL
21 ; 10ms
22 00001$: MOV R6, #49
23 00002$: MOV R7, #100
24 NOP
25 00003$: DJNZ R7, 00003$
26 DJNZ R6, 00002$
27 DJNZ R5, 00001$
28 __endasm;
29 }
30
31 /* **************************************************
32 * Hlavní program.
33 ****************************************************/
34
35 void main(void)
36 {
37 while (1) { // nekonečná smyčka
38 P0 = 0x0F; // 4 LED svítí, 4 LED nesvítí
39 delay_10m_x(20); // čekám 200 ms
40 P0 = 0xF0; // 4 LED nesvítí, 4 LED svítí
41 delay_10m_x(80); // čekám 800 ms
42 }
43
44 }
V tomto příkladu budeme generovat 3 krátké tóny. ÓÓÓvčááácíííí.
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: tuu-tuu.asm
3 ; Datum: 20.12.2011 09:33
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: 3 pípnutí reproduktoru
7 ; Popis: Akord C-dur
8 ; C1 262 <- T = 3816 us; T/2 = 1908 us
9 ; D1b 277
10 ; D1 294
11 ; E1b 311
12 ; E1 330 <- T = 3030 us; T/2 = 1515 us
13 ; F1 349
14 ; G1b 370
15 ; G1 392 <- T = 2551 us; T/2 = 1275 us
16 ; A1b 416
17 ; A1 440
18 ; B1b 466
19 ; B1 494
20 ; C2 523
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22
23 repro bit P1.7
24
25 akord:
26 ; tón C délky 650ms
27 mov R0,#170D
28 periodaC:
29 setb repro
30 call delayC
31 clr repro
32 call delayC
33 djnz R0, periodaC
34 ; tón E délky 650ms
35 mov R0,#214D
36 periodaE:
37 setb repro
38 call delayE
39 clr repro
40 call delayE
41 djnz R0, periodaE
42 ; tón G délky 650ms
43 mov R0,#254D
44 periodaG:
45 setb repro
46 call delayG
47 clr repro
48 call delayG
49 djnz R0, periodaG
50 ; přestávka
51 call del1s
52 ; zase znovu
53 jmp akord
54
55
56 delayC:
57 ; START: Wait loop, time: 1903 us
58 ; Clock: 12000.0 kHz (12 / MC)
59 ; Used registers: R7, R6
60 MOV R6, #005h
61 MOV R7, #0BCh
62 NOP
63 DJNZ R7, $
64 DJNZ R6, $-5
65 NOP
66 ; Rest: 0
67 ; END: Wait loop
68 RET
69
70 delayE:
71 ; START: Wait loop, time: 1510 us
72 ; Clock: 12000.0 kHz (12 / MC)
73 ; Used registers: R7, R6
74 MOV R6, #00Dh
75 MOV R7, #038h
76 NOP
77 DJNZ R7, $
78 DJNZ R6, $-5
79 ; Rest: 0
80 ; END: Wait loop
81 RET
82
83 delayG:
84 ; START: Wait loop, time: 1270 us
85 ; Clock: 12000.0 kHz (12 / MC)
86 ; Used registers: R7, R6
87 MOV R6, #003h
88 MOV R7, #0D1h
89 NOP
90 DJNZ R7, $
91 DJNZ R6, $-5
92 NOP
93 NOP
94 ; Rest: 0
95 ; END: Wait loop
96 RET
97
98 include delay12MHz.inc
99
100 END
Pokud si porovnáte předchozí příklad v Assembleru a následující příklad v jazyce C zjistíte, že zvuk generovaný v jazyce C tak úplně neladí. Je to proto, že časové zpoždění je zde řešeno poměrně nepřesně.
1 /*
2 * Soubor: tuu-tuu.c
3 * Datum: 20.12.2011 22:11
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha: 3 pípnutí reproduktoru
7 * Popis: Akord C-dur
8 * C1 262 <- T = 3816 us; T/2 = 1908 us
9 * D1b 277
10 * D1 294
11 * E1b 311
12 * E1 330 <- T = 3030 us; T/2 = 1515 us
13 * F1 349
14 * G1b 370
15 * G1 392 <- T = 2551 us; T/2 = 1275 us
16 * A1b 416
17 * A1 440
18 * B1b 466
19 * B1 494
20 * C2 523
21 ****************************************************/
22
23 #include <at89x52.h>
24
25 /** Funkce pro časové zpoždění 100 us až 25500 us.
26 * (Pro OSC 12.0 MHz) Časové zpoždění je vždy násobkem 100 us.
27 * Režije spojená s voláním funkce k zadanému zpoždění
28 * přidává ještě dalších 6 us.
29 *
30 * @param koef Celkové zpoždění = koef x 100us. */
31 void delay_100u_x(unsigned char koef)
32 {
33 koef; //pouze prázdný výraz, abych nedostával warning při kompilac
34 __asm
35 MOV R6, DPL
36 ; 100 us
37 00002$: MOV R7, #48
38 00003$: DJNZ R7, 00003$
39 NOP
40 DJNZ R6, 00002$
41 __endasm;
42 }
43
44 /****************************************************
45 * Hlavní program.
46 ****************************************************/
47
48 void main(void)
49 {
50 unsigned char i;
51
52 while (1) {
53 for ( i = 0; i < 170; i++) {
54 P1_7 = 0;
55 delay_100u_x(19);
56 P1_7 = 1;
57 delay_100u_x(19);
58 }
59 for (i = 0; i < 214; i++) {
60 P1_7 = 0;
61 delay_100u_x(15);
62 P1_7 = 1;
63 delay_100u_x(15);
64 }
65 for (i = 0; i < 254; i++) {
66 P1_7 = 0;
67 delay_100u_x(12);
68 P1_7 = 1;
69 delay_100u_x(12);
70 }
71 }
72
73 }
74
V tomto příkladu je použita knihovna pro časové zpoždění delay12MHz.inc
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: sem-tam.asm
3 ; Datum: 02.01.2012 23:06
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: světlo se pohybuje zleva doprava a
7 ; zprava doleva
8 ; Popis: ukázka skolků a logických operací
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10
11 ukazatel bit 0 ; symbolické jmeno pro ukazatel směru
12
13 ; počáteční nastavení
14 mov A, #01111111b ; svítí LED vlevo
15 setb ukazatel ; pohybuje se doprava
16
17 ; hlavní smyčka
18 start:
19 call roluj
20 call del100m
21 jmp start
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
24 ; podprogram posune světlo doleva nebo dobrava
25 roluj:
26 jnb ukazatel, vlevo ; doleva nebo doprava?
27 RR A
28 jmp posun
29 vlevo:
30 RL A
31 posun:
32 mov P0, A
33 call smer ; prehodi sme -- poku je to potreba
34 RET
35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36
37 ; podprogram přehodí směr posunu
38 smer:
39 jnb A.0, negace
40 jnb A.7, negace
41 RET
42 negace:
43 cpl ukazatel
44 RET
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46
47 include delay12MHz.inc ; definice zpoždění
48
49 END
Pro ilustraci uvádím ještě jedno řešení stejného problému:
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: sem-tam.asm
3 ; Datum: 02.01.2012 23:06
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: světlo se pohybuje zleva doprava a
7 ; zprava doleva
8 ; Popis: ukázka skolků a logických operací
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 smer bit 7 ; symbolické jmeno pro ukazatel směru
11
12 mov R0, #1d
13 setb smer ;; bit 5 označuje směr 1=vlevo 0= vpravo
14
15 ; hlavní proramová smyčka
16 start:
17 call zobrazuj
18 call del200m
19 jmp start
20
21
22 ; podprogram pro zobrazení světla na LED
23 zobrazuj:
24 mov A, R0
25 jb smer, rotujVlevo
26 jmp rotujVpravo
27 rotujVlevo:
28 RL A
29 jmp uloz
30 rotujVpravo:
31 RR A
32 jmp uloz
33
34 uloz:
35 mov R0, A ; uchovává číslo logicky
36 cpl A
37 mov P0, A ; P0 zobrazuje
38
39 ; kontroluju jestli jsem došel doleva -- pomocí CJNE
40 CJNE R0, #10000000b, preskoc
41 jmp vpravo
42 preskoc:
43 ; kontroluju jestli jsem došel doprava -- pomocí ANL
44 mov A, #00000001b
45 ANL A, R0
46 jnz vlevo
47 RET
48
49 ; otáčí směr pohyby doprava
50 vpravo:
51 clr smer
52 RET
53 ; otáčí směr pohybu doleva
54 vlevo:
55 setb smer
56 RET
57 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58
59
60 include delay12MHz.inc
61
62 END
I program v C používá malou knihovnu pro zpoždění:
1 /*
2 * Soubor: sem-tam.c
3 * Datum: 02.01.2012 23:47
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha:
7 * Popis:
8 ****************************************************/
9 #include <at89x52.h>
10
11 #include "delay12MHz.h"
12
13
14 /* **************************************************
15 * Hlavní program.
16 ****************************************************/
17
18 #define VLEVO 0
19 #define VPRAVO 1
20 void main(void)
21 {
22 __bit smer = VPRAVO;
23 unsigned char svetlo = 0b10000000;
24 for (;;) {
25 /* sviť */
26 P0 = ~svetlo;
27 /* rotace */
28 if (smer == VPRAVO) {
29 svetlo = svetlo >> 1;
30 } else if (smer == VLEVO) {
31 svetlo = svetlo << 1;
32 }
33 /* prohození směru */
34 if (svetlo == 128 || svetlo == 1) {
35 smer = !smer;
36 }
37 /* čekej */
38 delay_10m_x(10);
39 }
40 }
V těchto jednoduchých příkladech si všimněte použití symbolu PORT. Ten ukazuje na port P2, ale pokud bude 7-segmentový display umístěn na jiném portu lze ho velice jednoduše -- na jednom místě, změnit.
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: 7-segment.asm
3 ; Datum: 06.01.2012 12:32
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: Zobrazí na 7-segmenotvém displayi čísla 0-9.
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8
9 port EQU P2 ; definice symbolu
10
11 start:
12 mov port,#11000000b ; 0
13 call del800m
14 mov port,#11111001b ; 1
15 call del800m
16 mov port,#10100100b ; 2
17 call del800m
18 mov port,#10110000b ; 3
19 call del800m
20 mov port,#10011001b ; 4
21 call del800m
22 mov port,#10010010b ; 5
23 call del800m
24 mov port,#10000010b ; 6
25 call del800m
26 mov port,#11111000b ; 7
27 call del800m
28 mov port,#10000000b ; 8
29 call del800m
30 mov port,#10010000b ; 9
31
32 jmp start
33
34 include delay12MHz.inc
35
36 END
1 /*
2 * Soubor: 7-segment.c
3 * Datum: 06.01.2012 12:52
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha: Zobrazí na 7-segmenotvém displayi čísla 0-9.
7 ****************************************************/
8 #define _ISOC99_SOURCE
9 #define _GNU_SOURCE
10 #include <at89x52.h>
11
12 #include "delay12MHz.h"
13
14 /* *************** Makra ******************** */
15 #define PORT P2
16
17
18 /****************************************************
19 * Hlavní program.
20 ****************************************************/
21 int main(void)
22 {
23 while (1) {
24 PORT = 0b11000000; // 0
25 delay_10m_x(80);
26 PORT = 0b11111001; // 1
27 delay_10m_x(80);
28 PORT = 0b10100100; // 2
29 delay_10m_x(80);
30 PORT = 0b10110000; // 3
31 delay_10m_x(80);
32 PORT = 0b10011001; // 4
33 delay_10m_x(80);
34 PORT = 0b10010010; // 5
35 delay_10m_x(80);
36 PORT = 0b10000010; // 6
37 delay_10m_x(80);
38 PORT = 0b11111000; // 7
39 delay_10m_x(80);
40 PORT = 0b10000000; // 8
41 delay_10m_x(80);
42 PORT = 0b10010000; // 9
43 delay_10m_x(80);
44 }
45 return 0;
46 }
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: 7-seg-tab.asm
3 ; Datum: 06.01.2012 13:51
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: Na 7-segmentovém displayi cykluje čísla 0-9
7 ; Popis: Ukazka práce s tabulkou.
8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
10 mov DPTR, #segment ; uloží adresu tabulky
11 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12 tabulka:
13 mov R0, #0 ; nuluje při překroční čísla 9
14 smycka:
15 call zobrazuj
16 call del1s
17 inc R0 ; zvýší hodnotu R0 o 1
18 cjne R0, #10, smycka ; počítá jen do 10
19 jmp tabulka
20
21 ; podprogram přepíš registr R0 na port 7-segment
22 zobrazuj:
23 mov A, R0 ; v A je číslo, které chci zobrazit
24 movc A,@A+DPTR ; číslo, které chci zobrazit najdu v tabulce a uložím opět do A
25 mov P2, A ; zobrazím číslo vytažené z tabulky
26 RET
27
28 ;; tabulka číslic displaye
29 segment: db 11000000b ; 0
30 db 11111001b ; 1
31 db 10100100b ; 2
32 db 10110000b ; 3
33 db 10011001b ; 4
34 db 10010010b ; 5
35 db 10000010b ; 6
36 db 11111000b ; 7
37 db 10000000b ; 8
38 db 10010000b ; 9
39
40 include delay12MHz.inc
41
42 END
V jazyce C je místo tabulky, použit klasické pole. Paměťová řída __code říká, že se se pole nemá ukládat do paměti RAM, ale do paměti programu.
1 /*
2 * Soubor: 7-seg-pole.c
3 * Datum: 06.01.2012 14:49
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha: Na 7-segmentovém displayi cykluje čísla 0-9
7 * Popis: Práce s polem.
8 ****************************************************/
9 #define _ISOC99_SOURCE
10 #define _GNU_SOURCE
11 #include <at89x52.h>
12
13 #include "delay12MHz.h"
14
15 /* *************** Makra ******************** */
16 #define PORT P2
17
18
19 /****************************************************
20 * Hlavní program.
21 ****************************************************/
22 int main(void)
23 {
24 /* pole uložené v paměti programu představuje čísla na displayi */
25 __code char segment[] = { 0b11000000, //0
26 0b11111001, // 1
27 0b10100100, // 2
28 0b10110000, // 3
29 0b10011001, // 4
30 0b10010010, // 5
31 0b10000010, // 6
32 0b11111000, // 7
33 0b10000000, // 8
34 0b10010000 // 9
35 };
36 /* zobrazované číslo */
37 char cislo = 0;
38
39 while (1) {
40 PORT = segment[cislo]; // zobrazí
41 delay_10m_x(80); // čeká
42 if (cislo < 9) {
43 cislo++;
44 } else {
45 cislo = 0;
46 }
47
48 }
49
50 return 0;
51 }
V tomto programu se na display zobrazuje náhodné číslo v rozsahu 1-6. Využívám zde toho, že procesor je poměrně rychlý a proto při stisku tlačítka nikdy nevím, kolik strojových cyklů ho vlastně držím. Proto se na displayi zobrazí pokaždé jiné číslo.
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ; Soubor: hraci-kostka.asm
3 ; Datum: 09.01.2012 10:00
4 ; Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 ; Licence: GNU/GPL
6 ; Úloha: Hrací kostka
7 ; Popis: Po stisknutí tlačíta zobrazí 7-segmentovce náhodné
8 ; číslo.
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10
11 ; symbol pro bit, na kterém je ovládací tlačítko
12 TL bit P1.0
13
14 ; počáteční nastavení
15 mov DPTR, #segment
16 mov R0, #1d
17
18 ; hlavní smyčka, pokud není stiskuné tlačíto, jen se zobrazuje
19 kostka:
20 jnb TL, cykluj ; pokud je stisnuto tlačítko, volej cykluj
21 CALL zobrazuj
22 jmp kostka
23
24 ; dokud je stisknuté tlačítko, zvětšuj hodnotu R0
25 cykluj:
26 mov P2, #0FFH ; zhasni 7-segmentovku
27 clr P2.7 ; rozsviť tečku
28 inc R0 ; zvedni hodnotu R0
29 cjne R0, #7d, nenuluj ; počítej jen do 6.
30 mov R0, #1d
31 nenuluj:
32 jmp kostka
33
34 ; číslo z registru R0 zobrazí na 7-segmentovku
35 zobrazuj:
36 mov A, R0
37 movc A,@A+DPTR
38 mov P2, A
39 RET
40 ; tabulka zobrazení na 7-segmentovce
41 segment: db 11000000b ; 0
42 db 11111001b ; 1
43 db 10100100b ; 2
44 db 10110000b ; 3
45 db 10011001b ; 4
46 db 10010010b ; 5
47 db 10000010b ; 6
48 db 11111000b ; 7
49 db 10000000b ; 8
50 db 10010000b ; 9
51
52 include delay12MHz.inc
53
54 END
1 /*
2 * Soubor: hraci-kostka.c
3 * Datum: 09.01.2012 10:21
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha:
7 * Popis:
8 ****************************************************/
9 #define _ISOC99_SOURCE
10 #define _GNU_SOURCE
11 #include <at89x52.h>
12
13 /* *************** Makra ******************** */
14 #define DISPLAY P2
15 #define TECKA P2_7
16 #define TLACITKO (P1_0 == 0)
17
18
19 /* pole uložené v paměti programu představuje čísla na displayi */
20 __code char segment[] = {
21 0b11000000, //0
22 0b11111001, // 1
23 0b10100100, // 2
24 0b10110000, // 3
25 0b10011001, // 4
26 0b10010010, // 5
27 0b10000010, // 6
28 0b11111000, // 7
29 0b10000000, // 8
30 0b10010000 // 9
31 };
32
33
34 /****************************************************
35 * Hlavní program.
36 ****************************************************/
37 void main(void)
38 {
39 char cislo = 1;
40
41 /* Pokud je stisknuté tlačítko, tak se v proměnné cislo
42 * cykluje hodnota 1-6. Pokd tlačítko stisnuté není,
43 * hodnota proměnné cilo se zobrazuje na display. */
44 while (1) {
45 if (TLACITKO) {
46 DISPLAY = 0b01111111;
47 cislo = cislo < 6 ? cislo + 1 : 1;
48 } else {
49 DISPLAY = segment[cislo];
50 }
51 }
52 }
1 /*
2 * Soubor: sem-tam.c
3 * Datum: 02.01.2012 23:47
4 * Autor: Marek Nožka, nozka <@t> spseol <d.t> cz
5 * Licence: GNU/GPL
6 * Úloha: Světlo se pohybuje doleva a doprava
7 * Popis: Tlačítka řídí rychlost.
8 ****************************************************/
9 #include <at89x52.h>
10 #include <stdbool.h>
11
12 #include "delay12MHz.h"
13
14
15 /* **************************************************
16 * Hlavní program.
17 ****************************************************/
18
19 #define VLEVO 0
20 #define VPRAVO 1
21 // tlačítko, které zvyšuje rychlost
22 #define TLPLUS (P1_0 == 0)
23 // tlačítko, které snižuje rychlost
24 #define TLMINUS (P1_1 == 0)
25 // tlačítko, které zastavuje a spouští
26 #define TLSTOP (P1_2 == 0)
27 // (jak dlouho musím držet tlačítko, aby reagovalo) x 10 ms
28 #define DRZIM 10
29
30
31 /** Funkce se stará o zobrazování a prohozazování směru
32 * pohybu světla
33 */
34 void zobrazuj(void)
35 {
36 static bool smer = VPRAVO;
37 static unsigned char svetlo = 0b10000000;
38
39 /* sviť */
40 P0 = ~svetlo;
41 /* rotace */
42 if (smer == VPRAVO) {
43 svetlo = svetlo >> 1;
44 } else if (smer == VLEVO) {
45 svetlo = svetlo << 1;
46 }
47 /* prohození směru */
48 if (svetlo == 128 || svetlo == 1) {
49 smer = !smer;
50 }
51 }
52
53 /** Funkce zobrazí na 7segmentu orientačí hodnotu rychlosti
54 * (0 až 9)
55 */
56
57 void zobrazuj7(unsigned char cas)
58 {
59 /* pole uložené v paměti programu představuje čísla na displayi */
60 __code char segment[] = {
61 0b11000000, //0
62 0b11111001, // 1
63 0b10100100, // 2
64 0b10110000, // 3
65 0b10011001, // 4
66 0b10010010, // 5
67 0b10000010, // 6
68 0b11111000, // 7
69 0b10000000, // 8
70 0b10010000 // 9
71 };
72 P2 = segment[9 - (cas-1)/10 ];
73
74 }
75
76 /** Tato funkce se zpouští každých 10ms a kontroluje přidržení
77 * tlačítek.
78 */
79 void kontrolujPlusMinus(unsigned char * cas)
80 {
81 static unsigned char indikatorPlus = 0;
82 static unsigned char indikatorMinus = 1;
83 static bool drzimPlus = false;
84 static bool drzimMinus = false;
85 // tlačítko PLUS
86 if (TLPLUS) {
87 drzimPlus = true;
88 indikatorPlus++;
89 } else {
90 drzimPlus = false;
91 indikatorPlus = 0;
92 }
93 if (indikatorPlus > DRZIM) {
94 (*cas) = (*cas) <= 2 ? 2 : (*cas) - 1;
95 indikatorPlus = 0;
96 }
97 // tlačítko MINUS
98 if (TLMINUS) {
99 drzimMinus = true;
100 indikatorMinus++;
101 } else {
102 drzimMinus = false;
103 indikatorMinus = 0;
104 }
105 if (indikatorMinus > DRZIM) {
106 (*cas) = (*cas) >= 100 ? 100 : (*cas) + 1;
107 indikatorMinus = 0;
108 }
109 }
110
111 void main(void)
112 {
113 unsigned char cas = 50;
114 unsigned char i;
115 bool stop = false;
116 bool stopPamet = false;
117 for (;;) {
118 if (!stop) {
119 zobrazuj();
120 zobrazuj7(cas);
121 // realizuje zpoždění a zároveň kontroluje tlačítko
122 for (i = 0; i < cas; i++) {
123 delay_10m_x(1);
124 kontrolujPlusMinus(&cas);
125 }
126 }
127 // TLSTOP reaguje při uvolnění
128 if (!TLSTOP && stopPamet) {
129 stop = ! stop;
130 }
131 stopPamet = TLSTOP;
132 }
133 }