Uživatel:Zitkojos

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] SEMESTRÁLNÍ PRÁCE [tachometr na kolo]

Zadání semestrální práce:

Obdoba tachometru v cyklistice. Tachometr by měřil aktuální rychlost na základě frekvence spínání vnějšího magnetického kontaktu a nastaveném průměru kola. Aktuální rychlost by se zobrazovala na dvoumístné sedmisegmentovce. Tachometr bude posléze připevněn na kolo a odzkoušen.



Popis funkce a výpočetního algoritmu:

Obecně tachometry na kolo nabízejí spoustu, až někdy zbytečných funkcí. V extrémních případech chybí pouze už jen vodotrysk. Tachometr sestavený v rámci této semestrální práce, vypočítává aktuální rychlost a zobrazuje pomocí dvojice sedmisegmentových LED displayů. Z tohoto faktu vyplývá, že minimální rychlost bude 0 km/h a maximální 99 km/h. Implementovaný algoritmus výpočtu aktuální rychlosti, funguje na principu čítání konkrétně dlouhé smyčky(pomocí 16b čítače) a během této smyčky, jsou vyvolávána přerušení od změny na pinu PB0. Po načítání definované doby se z pomocného registru vyjme hodnota, udávající počet sepnutí, která nastala během čítané doby. Jelikož každé sepnutí signalizuje otočku kola o 360°, znamená to že byla ujeta vzdálenost S = 2*pi*r, kde "r" je poloměr kola.

Výpočet rychlosti:

                                                        v = [n*(2*pi*r)]/t     [r = 0.335m -> 2*pi*r = 2.105 m]  -->     v = [n*2.105]/t

Pokud zvolíme vhodnou dobu čítání (v našem případě 16*65536*1 us = 1.05s), zjednoduší se nám vztah pro výpočet rychlosti na:

                                                        v = n*2

Tento tvar je velice jednoduchý pro implementaci a zároveň definuje minimální rozlišení tachometru, tj. 2 km/h (rozlišovací schopnost cyklo tachometrů, někdy bývá i horší).


Zapojení tachometru



Schéma a popis zapojení:

Základními stavebními kameny v tomto zapojení je Atmega88, posuvný 8b registr 74HCT595, BCD ->7 seg. dekodéry 4543 a sedmisegmentovky HDSP_5503 (společná katoda). Napájení celého obvodu je zajištěno 5V DC(možno použít USB2). Pomocí SW se vypočtena hodnota rychlosti nahraje do 74DCT595. Nahrání probíhá v 8 cyklech, vždy po jedno bitu. Před nahráním daného bitu jsou data(bit) připravená na vstupu "DS" a pomocí sériových hodin "SH_CP" se data nahrají do posuvného registru, takto se vykoná nahrání 8 bitů(hodnota rychlosti, která je již přepočtena do formy BCD kódu) za sebou. Po nahrání 8bitů se aktivují paralelní hodiny "ST_CP" a celý registr se nahraje do dvojice BCD-7segment dekodérů. Hodnota z posuvného registru je ve formátu, kde první čtyři bity (Q0,Q1,Q2 a Q3) nesou informaci o jednotkách a horní polovina registru (Q4, Q5, Q6 a Q7) nesou informaci o desítkách, vypočtené rychlosti. Na daném schématu zapojení je ke každé sedmisegmentovce připojeno 7 rezistorů. Tyto rezistory slouží k nastavení pracovního bodu elementární diody v sedmisegmentovce. Na zkušebním obvodu bude však zapojen pouze jeden rezistor mezi katodu a zem, pro zjednodušení zapojení(nevýhoda tohoto zapojení je ta, že čím vyšší počet bude rozsvícených segmentů, tím menší bude jejich svítivost).

Schématické zapojení tachometru

ASM implementace:

.include "m88def.inc"
;********************
;Popis, zapojeni a deklarace
;********************
;-----
;popis
;-----
;Spolecna Anoda -> segment switch on: bit must equal to zero
;2 možnosti: A)citam napr 1 sec a pocitam pocet sepnuti
;			 B)citam kolikrat mi pretecet citac mezi dvema sepnutimi
;--------
;zapojeni
;--------
;spinac:	PB0
;SH_CP:		PC5
;ST_CP		PC4
;DS			PC3

;tens: Q7:D,Q6:C,Q5:B,Q4:A 
;units:Q3:D,Q2:C,Q1:B,Q0:A 

;-------------------------
;tabulka vektoru preruseni
;-------------------------
.org 0x000					;RESET
rjmp reset					

.org 0x003					;PCINT0
rjmp PCINT0interupt

.org 0x00D					;Timer1 overflow
rjmp Timer1OVF

reset:
sei					        ;global inter. enable
;--------
;zasobnik
;--------
ldi r16,high(ramend)
out sph,r16
ldi r16,low(ramend)
out spl,r16

;---------
;deklarace
;---------
.def pom 	 = r16
.def counter = r17			;8x (8bit reg)
.def number  = r18
.def n_switch= r19
.def CycleCNT= r21
.def speed   = r20
.def tens    = r4
.def units   = r5

.equ SH_CP   = 5			;PC5(SH_CP)
.equ ST_CP   = 4  			;PC4(ST_CP)
.equ DS	     = 3  			;PC3(DS)
.equ button  = 0

clr n_switch				;number of switch is null
clr cycleCNT				;number of time cycles is null

;portC
sbi DDRC,SH_CP
sbi DDRC,ST_CP
sbi DDRC,DS

;portB
sbi PORTB,button			;PD0 in(pull up)

;-------------------
;nastaveni preruseni
;-------------------

ldi pom,0b00000001			;activate PCIE0 -> PCINT7...0
sts PCICR,pom

ldi r16,0b00000001 			;Mask active inputs(allow PCINT0 only)
sts PCMSK0,pom	
	
;---------------------------------
;nastaveni citace (counter1 - 16b)
;----------------´----------------
							;WGM13,WGM12,WGM,11,WGM10 = 0(normal mode)
ldi pom,0b00000000			;COM1A1,COM1A0,COM1B1,COM1B0,-,-,WGM11,WGM10(1a1,1a0,1b1,1b0 = disconnet from OCA,OCB)			
sts  TCCR1A,pom

ldi pom,0b00000001			;ICNC1,ICES1,-,WGM13,WGN12,CS12,CS11,CS10(cs12,11,10 prescaler 0,0,1 = prsc = 1)
sts TCCR1B,pom

ldi pom,0b00000000			;FOC1A,FOC1B,-,-,-,-,-,-
sts TCCR1C,pom

ldi pom,0b00000001			;-,-,ICIE1,-,-,OCIE1B,OCIE1A,TOIE1(toie1:counter1 overflow interrupt enable)
sts TIMSK1,pom				;time interupt enable


;----------------
;nastaveni spanku(bacha na spanek->nereaguje pak citac)
;----------------
;ldi pom,0b00000101	 		;Power down mode
;out SMCR,pom 				;Sleep mode set

;*************
;hlavni smycka
;*************
main:	
	sei
rjmp main


;*****************
;obsluha preruseni
;*****************
;--------------
;citani sepnuti
;--------------
PCINT0interupt:
	sbis  PINB,button	
	inc   n_switch			;every switch on is +1
reti

;--------------------
;pri preteceni citace
;--------------------
Timer1OVF:
    ;sei mozna zde povolit, kdy by se seplo	
	inc cycleCNT			;(inc r21)
	ldi pom,16
	eor pom,cycleCNT
	breq speedcal
reti

;-------------------------------------
;Vypocet, prevod a zobrazeni rychlosti
;-------------------------------------
Speedcal:
    clr cycleCNT			;(clr r21)
	ldi pom,2
	mul n_switch,pom
	mov speed,r0
	clr n_switch			;clear switching reg
;.................................................
;if speed si higher then 99 a zaroven r1 je nulovy
;.................................................
	clr pom	
    eor pom,r1				;r1 must be clear
	brne setmax

    ldi pom,0x64		    ;100 -> pom
    cp pom,speed
	brmi setmax
;......................
;dekodovani(bin -> BCD)
;......................
	clr	    pom	    		
tens:
	subi	speed,10		;speed = speed - 10
	brcs	units			;abort if carry set
	subi	pom,-$10   		;pom   = pom + 10
	rjmp	tens			;loop again
units:
	subi	speed,-10		;speed--10
	add	speed,pom	
;.....................................................................................
;zobrazeni[tens:dec2(D2,C2,B2,A2) units:dec1(D1,C1,B1,A1)] Tens:Q7 - Q4 Units:Q3 - Q0
;.....................................................................................
skok:	
	mov   number,speed
	ldi   counter,8			;8x SHCP
	lds   r1,0b10000000		;mask for bit0	
jump1:    	
	mov   pom,number
	cbr   pom,0b01111111
    eor   pom,r1
	brne  set_DS1	  		;if 0.bit set go to: set_DS
	breq  noset_DS1			;if 0.bit non-set go to: noset_DS
set_DS1:
	sbi PORTC,DS			;DS = High
    rjmp outof1
noset_DS1:
	cbi PORTC,DS			;DS = Low
outof1:	
    cbi PORTC,SH_CP			
	sbi PORTC,SH_CP			;Write (one bit)	
		lsl   number	    ;one bit shift to right
		dec   counter	
		brne  jump1
	cbi PORTC,ST_CP		    
	sbi PORTC,ST_CP		    ;write whole register
ret



setmax:
	ldi speed,0x99
	rjmp skok			    
ret

Popis jednotlivých bloků:

Při každé změně úrovně na PB0, dochází k vyvolání přerušení. Zde se ohlídá, zda se jedná o sepnutí nebo rozepnutí, v případě sepnutí dochází k inkrementaci n_switch. V Timer1OVF se v případě přetečení čítače inkrementuje proměnná cycleCNT(celkově 16x), takto odměříme celkovou naměřenou dobu 1,05s (šlo by to také udělat předděličkou frekvence - 16x )

;--------------
;citani sepnuti
;--------------
PCINT0interupt:
	sbis  PINB,button	
	inc   n_switch			;every switch on is +1
reti

;--------------------
;pri preteceni citace
;--------------------
Timer1OVF:
    ;sei mozna zde povolit, kdy by se seplo	
	inc cycleCNT			;(inc r21)
	ldi pom,16
	eor pom,cycleCNT
	breq speedcal
reti

Speedcal - volá se po časovém úseku 1,05s z Timer1OVF. Má na starosti výpočet rychlosti a převod výsledku do BCD formy. V případě že rychlost je větší, než 99km/h, dochází k automatickému nastavení maximální rychlosti na 99km/h ve funkci setmax.

Speedcal:
        clr cycleCNT			;(clr r21)
	ldi pom,2
	mul n_switch,pom
	mov speed,r0
	clr n_switch			;clear switching reg
;.................................................
;if speed si higher then 99 a zaroven r1 je nulovy
;.................................................
	clr pom	
        eor pom,r1		        ;r1 must be clear
	brne setmax

        ldi pom,0x64		        ;100 -> pom
        cp pom,speed
	brmi setmax

Zde dochází k dekódování vypočtené rychlosti (speed) do formátu BCD. Důvodem je použití BCD -> 7 segment dekodérů. Převod převzat z [3].

;......................
;dekodovani(bin -> BCD)
;......................
	clr	    pom	    		
tens:
	subi	speed,10		;speed = speed - 10
	brcs	units			;abort if carry set
	subi	pom,-$10   		;pom   = pom + 10
	rjmp	tens			;loop again
units:
	subi	speed,-10		;speed--10
	add	speed,pom	

Zde dochází k načtení hodnoty rychlosti ve formě 8b čísla (formát BCD) do 8b posuvného sériově-paralelního registru (tzn. 4 bity pro jednotky a 4 bity pro desítky).

;.....................................................................................
;zobrazeni[tens:dec2(D2,C2,B2,A2) units:dec1(D1,C1,B1,A1)] Tens:Q7 - Q4 Units:Q3 - Q0
;.....................................................................................
skok:	
	mov   number,speed
	ldi   counter,8			;8x SHCP
	lds   r1,0b10000000		;mask for bit0	
jump1:    	
	mov   pom,number
	cbr   pom,0b01111111
        eor   pom,r1
	brne  set_DS1	  		;if 0.bit set go to: set_DS
	breq  noset_DS1			;if 0.bit non-set go to: noset_DS
set_DS1:
	sbi PORTC,DS			;DS = High
        rjmp outof1
noset_DS1:
	cbi PORTC,DS			;DS = Low
outof1:	
    cbi PORTC,SH_CP			
	sbi PORTC,SH_CP			;Write (one bit)	
                lsl   number	        ;one bit shift to right
		dec   counter	
		brne  jump1
	cbi PORTC,ST_CP		    
	sbi PORTC,ST_CP		        ;write whole register
ret


Možnosti pro vylepšení:

[1] Výpočet rychlosti na základě počtu zopakování malé časové smyčky(například 10ms - 100ms) v době mezi dvěma sepnutími magnetického kontaktu. Tento způsob by měl odstranit vliv časově nevhodného sepnutí kontaktu.

[2] Možnost výpočtu ujeté vzdálenosti a uložení do paměti.


Zdroje:

[1] http://www.kvetakov.net/clanky/avr/

[2] http://people.ee.duke.edu/~dwyer/courses/ece52/Binary_to_BCD_Converter.pdf

[3] http://www.edaboard.com/thread205066.html











Info:

DU0: Program pro řízení PWM výstupu pro větrák pomocí klávesnice(viz záložka 5.cvičení)(skupina: Josef Zitko, Dominik Vozák)

DU1: Odevzdání domácího úkolu (DU1): viz záložka 10.cvičení

DU2: Odevzdání domácího úkolu (DU1): úkol odevzdám v papírové formě



Zapojení: Soubor:ATtiny2313.png

[editovat] Organizace cvičení, bezpečnost práce, MAM wiki, vybavení laboratoře 362, program AVR Studio, Programování v jazyku C.

[editovat] Programování v jazyku C kód.

[editovat] Programátor AVR Dragon, mikroprocesory ATtiny2313 a ATmega88, instrukční soubor AVR, assembler, první pokus v assembleru v simulátoru AVR a spuštění programu přímo na procesoru.

pozn.: Jedná se o program, kterým jsme schopni blikat s připojenou dvoubarevnou diodou.(dvě barvy --> odlišné úbytky napětí, při stejné pracovním proudu) .EQU DDRB = $17 tímto způsobem zadáváme adresu konkrétní brány(posléze include). Podprogram WAIT, je vytvořen pomocí vnořených smyček, kdy elementární instrukce v dané smyčce trvají určitou dobu a celkové zpoždění je dáno právě množstvím cyklů v dané smyčce. Využívá se podmíněný skok BRNE WAIT --> skočí na WAIT, pokud výsledek instrukce nad ním byl roven nule(instrukce nad byla pouze inkrementování od nuly, kdy po přetečení 8 bit registru je zase nula --> 256 podcyklů)

; 
; example LED-show program for ATtiny 2313
;
; 2-color LED with 300 Ohm resistor in series is supposed to be
; connected between pins 12 (PB0, LED_X) and 13 (PB1, LED_Y).
;
; Color1 shines when LED_X is high and LED_Y is low
; Color2 shines when LED_Y is high and LED_X is low
; LED is off when LED_Y and LED_X are both low or both high


	.EQU DDRB = $17		; DDRB address
	.EQU PORTB = $18	; PORTB address
	

	.EQU LED_X = 0		; LED_X is on PB0, pin 12 of ATtiny2313
	.EQU LED_Y = 1		; LED_Y is on PB1, pin 13 of ATtiny2313

; Pins connected to LED are outputs, DDRx=1 (set):

	SBI	DDRB, LED_X	; SBI - Set Bit in I/O Register
	SBI	DDRB, LED_Y

SHOW:	
	RCALL	COLOR1	; RCALL - Relative Call to Subroutine
	RCALL	WAIT
	
	RCALL	DARK
	RCALL	WAIT
	
	RCALL	COLOR1
	RCALL	WAIT
	
	RCALL	DARK
	RCALL	WAIT
	
	RCALL	COLOR2
	RCALL	WAIT

	RCALL	DARK
	RCALL	WAIT
	
	RCALL	COLOR2
	RCALL	WAIT

	RCALL	DARK
	RCALL	WAIT

	RCALL	COL3W
	
	RCALL	DARK
	RCALL	WAIT

	RCALL	COL3W
	
	RCALL	DARK
	RCALL	WAIT
	
	RJMP SHOW		; RJMP - Relative Jump 

;;;
;;;
;;; P R O C E D U R E S
;;;
;;;
	
SMALLWAIT:
	INC	    R1				; INC - Increment
	BRNE	SMALLWAIT	; BRNE - Branch if Not Equal (Z flag) 
	RET					; RET - Return from Subroutine

WAIT:
	LDI	    R16, 4			; LDI - Load Immediate
WAIT1:	
    INC  	R1
	BRNE	WAIT1
	INC 	R2
	BRNE	WAIT1
	DEC	    R16
	BRNE	WAIT1
	RET
	
COLOR1:
    SBI	PORTB, LED_X
	CBI	PORTB, LED_Y	; CBI - Clear Bit in I/O Register
	RET

COLOR2:
    SBI	PORTB, LED_Y
	CBI	PORTB, LED_X
	RET

COL3W:
	LDI	R16, 2
COL3X: 	
    RCALL	COLOR1
	RCALL	SMALLWAIT
	RCALL	COLOR2
	RCALL	SMALLWAIT
	INC	    R2
	BRNE	COL3X
	DEC	    R16
	BRNE	COL3X

DARK:
    CBI	PORTB, LED_X
	CBI	PORTB, LED_Y
	RET

[editovat] Vstupní a výstupní porty, připojování periferií, maticová klávesnice, řízení LED, 1. domácí úkol

jak zjistit stav tlačítka:

1.pulling - neustálé zkoumání

2.pomocí instrukce načíst stav bitu - neukládat - načíst instrukcí podmíněného skoku - podle stavu - skákat instrukce SBIS (skip if bit is set)

SBIS PINC,2 = PC2 pokud je tam jednička skočí jinam, pokud není tak se provede něco dalšího.

SBIS -- jestli je rovno 1 SBIC -- jestli je rovno 0

pozn.: Nyní jsme již využili připojenou externí klávesnici. Nejdříve bylo využito jenom jedno tlačítko, ale dále bude používaná celá klávesnice. Detekce zmáčknutí tlačítka byla udělána takto: tlačítko bylo připojeno na dva bitové vstupy z jedné brány, kde jeden byl výstupní a druhý vstupní. Výstupní byl navolen na nulu(sbi DDRB,2; cbi PORTB,2 ) a vstupní byl navolen s pull-up rezistorem(cbi DDRB,3; sbi PORTB,3). Pokud je tlačítko rozepnuto je na PINB,3 měkká jednička a pokud se sepne tak ta měkká jednička se rozruší a bude tam nula, dle které se řídíme. Využívá se instrukce SBIS(SBIS PINB,3), která skáče na druhou instrukci pokud je na PINB,3 ta měkká jednička. Pozor u klávesnice na případ, kdy by se zmáčklo více jak jedno tlačítko --> může dojít ke zkratu kdy by se spojila jednička a nula(zde jsou cca 3 možné kombinace které se musejí ohlídat). Rozlišení které tlačítko bylo zmáčknuto se dělá tak, že se cyklicky mění řádek ve kterém je připojena nula(úroveň Low) a pak se reaguje, kdy se na těch vstupních pinech objeví nula, ta se tam objeví tehdy, když se spojí tlačítko na kterém je úroveň Low a proto se ví o který řádek jde a poté pomocí toho bitu který je vstupní a nulový se pozná i sloupec.


; 
; example LED-show program for ATtiny 2313
;
; 2-color LED with 300 Ohm resistor in series is supposed to be
; connected between pins 12 (PB0, LED_X) and 13 (PB1, LED_Y).
;
; Color1 shines when LED_X is high and LED_Y is low
; Color2 shines when LED_Y is high and LED_X is low
; LED is off when LED_Y and LED_X are both low or both high


	

	.EQU LED_X = 0		; LED_X is on PB0, pin 12 of ATtiny2313
	.EQU LED_Y = 1		; LED_Y is on PB1, pin 13 of ATtiny2313


	.EQU DDRB = $17
	.EQU PORTB = $18
	.EQU PINB = $16

	.EQU DDRD = $11
	.EQU PORTD = $12
	.EQU PIND = $10


; Pins connected to LED are outputs, DDRx=1 (set):

	SBI	DDRB, LED_X	; SBI - Set Bit in I/O Register
	SBI	DDRB, LED_Y
	CBI DDRB, 2
	SBI DDRD, 2        ;PD2 is output - ROW
                       ;CBI PORTD, 2  ; PD2=0
                       ;CBI DDRC, 2   ; PC2 is input - COLUMN	

	SBI PORTB,2       ;enables pull-up resistor on this pin
	CBI PORTD,2
	
	
  GO:
	RCALL   COLOR1
	RCALL	WAIT
	SBIS	PINB, 2
	RCALL	COLOR2
	RCALL	WAIT
	RJMP	GO
	



;;;
;;;
;;; P R O C E D U R E S
;;;
;;;
	
SMALLWAIT:
	INC	R1				; INC - Increment
	BRNE	SMALLWAIT	; BRNE - Branch if Not Equal (Z flag) 
	RET					; RET - Return from Subroutine

WAIT:
	LDI	R16, 4			; LDI - Load Immediate
WAIT1:	INC	R1
	BRNE	WAIT1
	INC	R2
	BRNE	WAIT1
	DEC	R16
	BRNE	WAIT1
	RET
	
COLOR1:
    SBI	PORTB, LED_X
	CBI	PORTB, LED_Y	; CBI - Clear Bit in I/O Register
	RET

COLOR2:
    SBI	PORTB, LED_Y
	CBI	PORTB, LED_X
	RET

COL3W:
	LDI	R16, 2
COL3X: 	RCALL	COLOR1
	RCALL	SMALLWAIT
	RCALL	COLOR2
	RCALL	SMALLWAIT
	INC	R2
	BRNE	COL3X
	DEC	R16
	BRNE	COL3X

DARK:
    CBI	PORTB, LED_X
	CBI	PORTB, LED_Y
	RET

[editovat] Výkonové spínací prvky, úloha na regulaci ventilátoru, přerušení, uspání procesoru

Sleep and Interrupt

Sleep:(pouze se nahraje do registru SMCR hodnota uvádějící stav spánku a následně smyčka pro spánek -> ze spánku se probudí při přerušení a navrátí při RETI )

ldi r16,0b00000101 ; Power down mode
	out SMCR,r16 ; Sleep mode set

loop:
	sleep 
	nop 
	rjmp loop

Interrupt:(nastaveni zásobníku na konec --> nastaví se kam skákat při konkrétním přerušení, povolí se přerušení globálně "sei" a nastaví se povolení přerušení pro konkrétní periferii a její konkrétní vstupy)

.ORG 0x0000 
	jmp Main ; Reset Handler

.ORG 0x0008 
	jmp isr1 ; PCINT1 Handler

main:

ldi R16,high(RAMEND)
out SPH,R16
ldi R16,low(RAMEND)
out SPL,R16


; Keyboard interrupt  
;
; Activation of pin change interrupt - PROBLEM!!! PCICR and PCIMSK are 
; extended I/O registers (0x68 and 0x6C), and must be handled as 
; a memory location

;	ldi r16,0x02 ; activate PCINT1
;	out PCICR,r16

	ldi r26, PCICR ; load address of PCICR in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00000010 ; activate PCINT1
	st X, r16 ; store new PCINT1


;	ldi r16,0b00011100 ; Mask active inputs
;	out PCMSK1,r16

	ldi r26, PCMSK1 ; load address of PCMSK1 in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00011100 ; allow pin change interrupt on portC bits 2,3,4
	st X, r16 ; store new PCMSK1


	sei ; Enable interrupts



SW udělaná PWM

; 
; example fan program for ATmega88
;
; P4 CPU fan Ucc pin is supposed to be connected 
; to +12 V, GND pin is supposed to be connected 
; to FET Drain, Source on GND, Gate on 
; pin 16 (PB2, FAN). Fan runs when FAN output is log. H.
;
; FAN is switched ON with switch between PC2 and PD2


	.EQU DDRB = $04
	.EQU PORTB = $05

	.EQU DDRC = $07
	.EQU PORTC = $08
	.EQU PINC = $06

	.EQU DDRD = $0A
	.EQU PORTD = $0B
	.EQU PIND = $09

;	.INCLUDE "m88def.inc"  ; replaces previous lines of the program

	.EQU FAN = 2


; Pin driving FAN is set as output:

	SBI	DDRB, FAN

; Basic keyboard init:

; One switch of matrix keyboard is connected between PINC 2 a PIND 2
; Zero values of DDRC, 2 and PORTB, 2 are implicit

	SBI DDRD, 2
	SBI PORTC, 2


; Init:
	RCALL   FAN_OFF


;klavesnice 7 a 3
   cbi DDRC,3  ;vstup
   sbi DDRD,1  ;vystup

   cbi PORTD,2  ;vystup nula
   sbi PORTC,3  ;nastavenej pul up


GO:	SBIS	PINC, 2
	RCALL	KEY7   ; Simple PWM control of the FAN, if the key is pressed
	SBIS    PINC, 3
	RCALL   KEY3
	RJMP	GO


;;;
;;;
;;; P R O C E D U R E S
;;;
;;;
	
VERYSMALLWAIT:
	LDI R20, 0xFC
	MOV R1, R20
SMALLWAIT:
	INC	R1
	BRNE	SMALLWAIT
	RET

	
FAN_ON:
	SBI	PORTB, FAN
	RET

FAN_OFF:
	CBI	PORTB, FAN
	RET


PWM:
	MOV 	R17, R16
	INC		R17
	LDI		R18, 0xF8
	OR		R18, R16
PWM_ON:
	DEC		R17
	BREQ	PWM_OFF
	SBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_ON
PWM_OFF:
	INC		R18
	BREQ	PWM_RET
	CBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_OFF
PWM_RET:
	RET


KEY7:
ldi R16,8
rcall PWM
ret

KEY3:
ldi R16,1
rcall PWM	
ret



PROGRAM: Klávesnicí řízení PWM výstup pro větrák(skupina Josef Zitko, Dominik Vozák)


.INCLUDE "m88def.inc"
;*********
;Zapojeni:
;*********
;radky:		col1(PD1);	col2(PD2);	col3(PD3);	col4(PD4)
;sloupce:	row1(Pb1);	row2(Pb2);	row3(Pb3);	row4(Pb4)
;PWM out:	Pd5

;**********
;definovani
;**********
	.EQU IN1 = 1		;col1
	.EQU IN2 = 2		;col2
	.EQU IN3 = 3		;col3
	.EQU IN4 = 4		;col4
 
	.EQU OUT1 = 1		;row1
	.EQU OUT2 = 2		;row2
	.EQU OUT3 = 3		;row3
	.EQU OUT4 = 4	 	;row4

    .def citac		= r19
	.equ PWM_PULSES = 0
	.equ PWM_OUT    = 5 ; Pd5 PWM out

;-------------
;nastaveni PWM
;-------------
PWM_INIT:
	ldi R17, 0b00100011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17			; 
	ldi R17, 0b00001001	; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1)
	out TCCR0B, R17
	ldi R17, PWM_PULSES	; load number of clock pulses for 1 PWM period
	out OCR0A, R17   

	sbi DDRD, PWM_OUT	; set pin 11 as PWM output OC0B (PD5 pin)

;vypnuti PWM
	ldi R17, 0b00000011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17	


;---------------
;nastaveni portu
;---------------
cbi DDRD, IN1			;Pd1 in
sbi PORTD,IN1			;Pd1 pull-up on

cbi DDRD, IN2			;Pd2 in
sbi PORTD,IN2			;Pd2 pull-up on

cbi DDRD, IN3			;Pd3 in
sbi PORTD,IN3			;Pd3 pull-up on

cbi DDRD, IN4			;Pd4 in
sbi PORTD,IN4			;Pd4 pull-up on

;nastaveni (take jako vystupni - tu jednu budu vzdy prepinat do vstupu)
cbi DDRB,OUT1			;Pb1 in
cbi DDRB,OUT2			;Pb2 in
cbi DDRB,OUT3			;Pb3 in
cbi DDRB,OUT4			;Pb4 in



;*************
;Hlavni smycka
;*************	
MAIN:
	ldi R17, 0b00000011	;vypnuti PWM
	out TCCR0A, R17	
	RCALL STISK
RJMP MAIN




;***********
;podprogramy
;***********

STISK:
;Nic nedela pokud neni seple jen jedno tlacitko
;---------------------------------------------------------------------------
	clr 	citac		;vynulovani pom registru
	in      R16,sreg
	cbr     R16,0b00000010	
	out     sreg,R16	;vynulovani sreg po clr(pro sychr)

	;************(zakomentovanim se multiple touch ochrana vypne)
	sbi DDRB,OUT1		;out
	cbi PORTB,OUT1		;Pb1 out Low
	sbi DDRB,OUT2		;out
	cbi PORTB,OUT2		;Pb1 out Low
	sbi DDRB,OUT3		;out
	cbi PORTB,OUT3		;Pb1 out Low
	sbi DDRB,OUT4		;out
	cbi PORTB,OUT4		;Pb1 out Low
	;*************

	SBIS 	PIND,IN1
	RCALL 	VICETLAC
	SBIS 	PIND,IN2
	RCALL 	VICETLAC
	SBIS 	PIND,IN3
	RCALL 	VICETLAC
	SBIS 	PIND,IN4
	RCALL 	VICETLAC
   
	ldi 	R16,0b00000001
	eor 	R16,citac
	brne    SKOK		;skoci jen kdyz v citaci bude 0b00000001(pouze jedno zmackle)
;----------------------------------------------------------------------------


;1.radek je low
    sbi DDRB,OUT1		;out
	cbi PORTB,OUT1		;Pb0 out Low
cbi PORTB,OUT2	    	;Pb1 in 
cbi PORTB,OUT3			;Pb2 in 
cbi PORTB,OUT4			;Pb3 in 

;kontrola jestli je na vstupu nula(mozna tlacitka 1,2,3,A)
SBIS 	PIND,IN1
RCALL 	PROG1
SBIS 	PIND,IN2
RCALL 	PROG2
SBIS 	PIND,IN3
RCALL 	PROG3
SBIS 	PIND,IN4
RCALL 	PROGA

;2.radek je low
cbi PORTB,OUT1			;Pb0 in 
	sbi DDRB,OUT2		;out
	cbi PORTB,OUT2		;Pb1 out Low
cbi PORTB,OUT3			;Pb2 in 
cbi PORTB,OUT4			;Pb3 in 

;kontrola jestli je na vstupu nula(mozna tlacitka 4,5,6,B)
SBIS 	PIND,IN1
RCALL 	PROG4
SBIS 	PIND,IN2
RCALL	PROG5
SBIS 	PIND,IN3
RCALL 	PROG6
SBIS 	PIND,IN4
RCALL 	PROGB

;3.radek je low
cbi PORTB,OUT1			;Pb0 in 
cbi PORTB,OUT2			;Pb1 in 
	sbi DDRB,OUT3		;out
	cbi PORTB,OUT3		;Pb2 out Low
cbi PORTB,OUT4			;Pb3 in 

;kontrola jestli je na vstupu nula(mozna tlacitka 7,8,9,C)
SBIS 	PIND,IN1
RCALL 	PROG7
SBIS 	PIND,IN2
RCALL 	PROG8
SBIS 	PIND,IN3
RCALL 	PROG9
SBIS 	PIND,IN4
RCALL 	PROGC

;4.radek je low
cbi PORTB,OUT1			;Pb0 in 
cbi PORTB,OUT2			;Pb1 in 
cbi PORTB,OUT3			;Pb2 in 
	sbi DDRB,OUT4		;out
	cbi PORTB,OUT4		;Pb3 out Low

;kontrola jestli je na vstupu nula(mozna tlacitka *,0,#,D)
SBIS 	PIND,IN1
RCALL 	PROGHVEZD
SBIS 	PIND,IN2
RCALL 	PROG0
SBIS 	PIND,IN3
RCALL 	PROGMRIZ
SBIS 	PIND,IN4
RCALL 	PROGD

SKOK:
RET

;-----------------------
;pri zmacnuti klavesnice
;-----------------------

PROGA:					;stisk A
ret

PROGB:					;stisk B
ret

PROGC:					;stisk C
ret

PROGD:					;stisk D
ret

PROGHVEZD:				;stisk *
ret

PROGMRIZ:				;stisk #
ret

PROG1:					;stisk 1
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,2
out OCR0A, R17 
ret

PROG2:					;stisk 2
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,4
out OCR0A, R17 
ret

PROG3:					;stisk 3
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,6
out OCR0A, R17 
ret

PROG4:					;stisk 4
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,8
out OCR0A, R17 
ret

PROG5:					;stisk 5
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,10
out OCR0A, R17 
ret

PROG6:					;stisk 6
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,14
out OCR0A, R17 
ret

PROG7:					;stisk 7
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,18
out OCR0A, R17 
ret

PROG8:					;stisk 8
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,22
out OCR0A, R17 
ret

PROG9:					;stisk 9
ldi R17, 0b00100011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
clr R17
ldi R17,32
out OCR0A, R17 
ret

PROG0:					;stisk 0
ldi R17,0
out TCCR0A, R17
ldi R17, 0b00000011		; Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, R17	
ret


;-------
;ostatni
;-------
VICETLAC:   			;stisk vice tlacitek
inc citac
ret


[editovat] Čítače, časovače a PWM výstupy, zdroje hodinového signálu, přesný reálný čas.


[editovat] Složitější periferie, A/D převodníky a analogový komparátor. Ukázka zesilovače v třídě D s ATtiny45.

[editovat] Posuvný registr jako výstupní periferie, připojení sedmisegmentového displeje. Rozdělení samostatných prací.

.include "m88def.inc"
;********************
;Popis, zapojeni a deklarace
;********************
;-----
;popis
;-----
;maximum clock frequency SH_CP and ST_CP 74HC(100MHz) 74HCT(57MHz)
;Pomoci zmacknuteho/nezmacknuteho tlacitka ovladam, kterej ze dvou cisel
;bude zobrazeno(sepnuto = num1; nesepnuto = num2)
;s přerušením od tlačítka!!!!

;Spolecna Anoda -> segment switch on: bit must equal to zero

;--------
;zapojeni
;--------
;spinac:	PB0
;SH_CP:		PC5
;ST_CP		PC4
;DS			PC3
;---------------------------
;numbers(sviti nuly SPAnoda)
;---------------------------
;zapojeni:
;Q0:A(7)|Q1:B(6)|Q2:C(4)|Q3:D(2)|Q4:E(1)|Q5:F(9)|Q6:G(10)|Q7:Dp(5)

;0b11000000;//0 
;0b11111001;//1 
;0b10100100;//2 
;0b10110000;//3 
;0b10011001;//4 
;0b10010010;//5 
;0b10000010;//6 
;0b11111000;//7 
;0b10000000;//8 
;0b10010000;//9 

;-------------------------
;tabulka vektoru preruseni
;-------------------------
.org 0x000
rjmp reset					;reset

.org 0x003					;PCINT0
rjmp PCINT0interupt


reset:
sei					        ;global inter. enable
;--------
;zasobnik
;--------
ldi r16,high(ramend)
out sph,r16
ldi r16,low(ramend)
out spl,r16

;---------
;deklarace
;---------
.def pom 	 = r16
.def counter = r17			;8x (8bit reg)
.def number  = r18

.equ SH_CP   = 5			;PC5(SH_CP)
.equ ST_CP   = 4  			;PC4(ST_CP)
.equ DS	     = 3  			;PC3(DS)
.equ button  = 0

;portC
sbi DDRC,SH_CP
sbi DDRC,ST_CP
sbi DDRC,DS

;portB
sbi PORTB,button			;PD0 in(pull up)

;-------------------
;nastaveni preruseni
;-------------------

ldi pom,0b00000001			;activate PCIE0 -> PCINT7...0
sts PCICR,pom

ldi r16,0b00000001 			;Mask active inputs(allow PCINT0 only)
sts PCMSK0,pom			

;----------------
;nastaveni spanku
;----------------
ldi pom,0b00000101	 		;Power down mode
out SMCR,pom 				;Sleep mode set

;*************
;hlavni smycka
;*************
main:
	sleep
	nop
rjmp main



;*****************
;obsluha preruseni
;*****************
PCINT0interupt:
	sbis  PINB,button
	rcall push_button		;pushed button
	sbic  PINB,button
	rcall not_push_button	        ;no pushed button
reti

;**********
;procedures
;**********
;----------------------
;push or not_pus button
;----------------------
push_button:				;number one		    	
	ldi   number,0b10000010         ;number one = 6
	ldi   counter,8			;8x SHCP
	lds   r1,0b10000000             ;mask for bit0	
jump0:    	
	mov   pom,number
	cbr   pom,0b01111111
    eor   pom,r1
	brne  set_DS0	  		;if 0.bit set go to: set_DS
	breq  noset_DS0			;if 0.bit non-set go to: noset_DS
set_DS0:
	sbi PORTC,DS			;DS = High
    rjmp outof0
noset_DS0:
	cbi PORTC,DS			;DS = Low	
outof0:	
    cbi PORTC,SH_CP			
	sbi PORTC,SH_CP			;Write(one bit)	
		lsl   number		;one bit shift to right
		dec   counter	
		brne  jump0
    cbi PORTC,ST_CP		    
	sbi PORTC,ST_CP		        ;write whole register	
ret




not_push_button:			;number two
	ldi   number,0b11111000 ;number one = 7
	ldi   counter,8			;8x SHCP
	lds   r1,0b10000000		;mask for bit0	
jump1:    	
	mov   pom,number
	cbr   pom,0b01111111
    eor   pom,r1
	brne  set_DS1	  		;if 0.bit set go to: set_DS
	breq  noset_DS1			;if 0.bit non-set go to: noset_DS
set_DS1:
	sbi PORTC,DS			;DS = High
    rjmp outof1
noset_DS1:
	cbi PORTC,DS			;DS = Low
outof1:	
    cbi PORTC,SH_CP			
	sbi PORTC,SH_CP			;Write (one bit)	
		lsl   number	        ;one bit shift to right
		dec   counter	
		brne  jump1
	cbi PORTC,ST_CP		    
	sbi PORTC,ST_CP		    ;write whole register
ret

[editovat] Jazyk C a jeho překlad pomocí GCC a programu make, ISP pomocí avrdude. Optimalizace rychlosti, optimalizace využití RAM, kombinace C a assembleru, C intrinsics

#include <avr/interrupt.h>
#include <avr/sleep.h>

#define SER		PD5
#define SRCLK	PD6
#define RCLK	PD7
#define SRCLR	PB0

// global constants and variables
// static code table used for 7-segment led display decoding (common anode)
/*unsigned char code [] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x9B, 0x92, 0x93, 0xF8, 0x80, 0x98,
				 		  0x88, 0x80, 0xC6, 0xC0, 0x86, 0x8E };*/
unsigned char code [] = { 0x3F, 0x06, 0x5B, 0x4F, 0x64, 0x6D, 0xFC, 0x07, 0x7F, 0x67,
				 		  0xF7, 0x7F, 0x39, 0x3F, 0x79, 0x71 };

// character to show on display
static volatile unsigned char anumber = 0;
// Interrupt vector table is created by compiler
// the ISR macro defines interrupt service handlers

// Pin change interrupt 1
// keyboard handler
ISR(PCINT1_vect)
{
	unsigned char keys[10];
	unsigned char nkeys = 0;
	register unsigned char column;

//    DDRD 	&= 0b00000001;
	DDRD	&= 0b11110001;
	PORTD	&= 0b11110000;		// set keyboard rows at port D to zero
	if (!(PINC & 4))
		keys[nkeys++] = 1;
	if (!(PINC & 8))
		keys[nkeys++] = 2;
	if (!(PINC & 16))
		keys[nkeys++] = 3;

	DDRD	&= 0b11110000;
	DDRD	|= (1 << PD1);
	PORTD	&= 0b11110000;		// set keyboard rows at port D to zero
	if (!(PINC & 4))
		keys[nkeys++] = 4;
	if (!(PINC & 8))
		keys[nkeys++] = 5;
	if (!(PINC & 16))
		keys[nkeys++] = 6;

	DDRD	&= 0b11110000;
	DDRD	|= (1 << PD2);
	PORTD	&= 0b11110000;		// set keyboard rows at port D to zero
	if (!(PINC & 4))
		keys[nkeys++] = 7;
	if (!(PINC & 8))
		keys[nkeys++] = 8;
	if (!(PINC & 16))
		keys[nkeys++] = 9;

	DDRD	&= 0b11110000;
	DDRD	|= (1 << PD3);
	PORTD	&= 0b11110000;		// set keyboard rows at port D to zero
	if (!(PINC & 8))
		keys[nkeys++] = 0;

	DDRD 	|= 0b00001111;		// configure rows as outputs
	PORTD 	&= 0b11110000;		// set keyboard rows at port D to zero

	if (nkeys > 0) {
		OCR1A = keys[0] * 100;
		TCNT1 = 0;
	}
}

// Timer/Counter1 Compare Match A
// the value shown on the display will be updated here
ISR(TIMER1_COMPA_vect)
{
	unsigned char tmp = code[anumber];
	volatile char loopcounter = 8;

	do {
		PORTD &= ~(1 << SRCLK);			// assert 0 on serial clock line
		if (tmp & 0x80)					// test LSB
			PORTD |= (1 << SER);		// if 1, assert 1 on serial data line
		else
			PORTD &= ~(1 << SER);		// assert 0 otherwise
		PORTD |= (1 << SRCLK);			// assert 1 on serial clock line - rising edge writes bit into the serial shift register
		tmp <<=  1;					// shift right to proceed next bit
		loopcounter--;
	} while (loopcounter > 0); 
	PORTD &= ~(1 << RCLK);				// toggle parallel register clock 0-1 to make a rising edge
	PORTD |= (1 << RCLK);
	
	// update value to display for next time
	if (anumber < 15)
	    anumber++;
	else
		anumber = 0;
}

void main(void)
{
	// keyboard (and serial shift register connection) ports init
	DDRD 	|= 0b11101111;		// configure rows as outputs (PD0 ... PD3), serial shift register pins PD5 .. PD7
	PORTD 	= 0;				// set port D to zero
	DDRC	= 0;				// configure port C as input port
	PORTC	|= 0b00011100;		// activate pul-up resistors on three columns

	DDRB	|= (1 << SRCLR);	// configure PB0 as output - serial shoft register clear
	PORTB	|= (1 << SRCLR);	// toggle PB0 1-0-1 to clear the serial shift register
	PORTB	&= ~(1 << SRCLR);
	PORTB	|= (1 << SRCLR);

	// an interrupt masking must be here
	// keyboard interrupt
	PCICR 	= (1 << PCIE1);		// Pin change interrupt control register, Pin change interrupt enable 1
	PCMSK1 	= 0b00011100;		// allow pin change interrupt on portC bits 2,3,4

	// timer configuration
	TCCR1A	= 0;				// OC1A/OC1B disconnected, CTC bits WGM11, WGM10
	TCCR1B 	= (1 << CS12) | (1 << CS10) | (1 << WGM12);
								// CTC mode, prescaler division factor 1024
	OCR1A 	=  978;				// timer compare value

	TIMSK1 = (1 << OCIE1A);		// enable timer interrupt

	set_sleep_mode(SLEEP_MODE_IDLE);
	sei();						// set Global Interrupt Enable!!!

	while (1) {
		sleep_cpu();
	}
}

[editovat] Teoreticky vnější RAM, externě připojené vstupy a výstupy, odevzdání 1. domácího úkolu na osobní stránce zde na Wiki, zadání 2. domácího úkolu.

DOMÁCÍ ÚKOL1
osvětlení automobilu
.include "m88def.inc"
;******
;zadani
;******
;Zvolte vhodné zapojení a procesor a v assembleru naprogramujte 2 na sobě nezávislé PWM regulace
;osvětlení do auta. Jedna je pro vnitřní osvětlení, po sepnutí dveřního kontaktu nastaví okamžitě
;plný svit, po rozpojení ještě asi 5 s plný svit a následuje asi 2 sekundy dosvit s poklesem od
;maxima do nuly, druhá PWM je pro regulované osvětlení palubní desky, vstup potenciometr, výstup
;výkonová PWM regulace asi 10 % až 100 %. Napájecí napětí auta je 12 V, špičky rušení mohou dosáhnout
;až 20 V.

;špičky v Vcc pomocí stabilizatoru napětí(např.MC7805CTG)


;********
;zapojeni
;********
;tlacitko: 	na PB0 a GND
;potenciometr: 	na PC0 - ADC0
;LED1 a LED2: 	na LED1(PD5(OC0B)-zelena), LED2(PD3(OC2A)-cervena)
;kondenzator:   na AREF

;***************
;preddefinovani
;***************
.def pom 	    = r16
.def citac 	    = r17
.def PWM2_poc_pulsu = r20	;value for 1MHz/10 PWM (plný svit) - palubka
.def PWM1_poc_pulsu = r21	;value for 1MHz/ PWM (plný svit) - interier

.equ tlacitko       = 0	

;-------------------------
;tabulka vektoru preruseni
;-------------------------
.org 0x000
rjmp reset

.org 0x015
rjmp ADCconv_compl


reset:
sei   				;globalni povoleni preruseni
;--------
;zasobnik
;--------
ldi pom,high(ramend)
out sph,pom
ldi pom,low(ramend)
out spl,pom

;---
;def
;---
ldi citac,0xf0			;pomocna pro citac
ldi PWM2_poc_pulsu,2
ldi PWM1_poc_pulsu,2

;----------------
;inicializace ADC
;----------------
ldi pom, 0b11100000		;interní 1.1V reference s kapacitorem na pinu AREF, zarovnání výsledku vlevo, vstup na ADC0
sts ADMUX, pom				
ldi pom, 0b11101101		;ADC "zapnut", int. off, autotriger off, dělící faktor 32 (31,250kHz),ADATE(1): povoleni ciziho zapnuti adc
sts ADCSRA,pom			;ADC control and status register A; ADIE=1(AD interrupt enable)
ldi pom, 0b00000000		;autotriger on: adts2:0 = 000 (free running)
sts ADCSRB, pom		
ldi pom, 0b00000001		
sts DIDR0,pom			;reduce power consumption in the digital input buffer(on ADC0pin)			

;---------------
;deklarace portu
;---------------
;portB
ldi pom,0b00000000
out DDRB,pom
ldi pom,0b00000001
out PORTB,pom

;portD
ldi pom,0b00101000
out DDRD,pom
ldi pom,0b00000000
out PORTD,pom

;portC
ldi pom, 0b000000	    	;PC0 je vstup ADC 
out DDRC, pom			
ldi pom, 0b000000		;vstupy


;----------------------
;deklarace PWM interier
;----------------------
ldi pom, 0b00100011		;Fast PWM Mode, out on OC0B, non Inverting
out TCCR0A, pom			 
ldi pom, 0b00001001		;WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1)
out TCCR0B, pom
mov pom, PWM1_poc_pulsu		;load number of clock pulses for 1 PWM period
out OCR0A, pom
ldi pom, 0b00000011		;com0b1, com0b0 = 0,0 0CO disconnected	"zakmitani"
out	TCCR0A, pom

;-------------------------------------------------------
;deklarace PWM palubka - nemusim odpojovat --> 10 - 100%
;-------------------------------------------------------
				;nastaveni shodne jako TMR0, jen jiny zpusob, protoze registry nejsou dostupne pomoci "out"
ldi pom, 0b00100011		;rychlá PWM, výstup na OC2B (PD3), neinvertující
sts TCCR2A, pom			;TCCR - time counter control register
ldi pom, 0b00001001		;rychlá PWM, vnitřní hodiny, prescale=1
sts TCCR2B, pom			
mov pom, PWM2_poc_pulsu		;load number of clock pulses for 1 PWM period
sts OCR2A, pom	
			
;*************
;hlavni smycka
;*************
main:
	sbic  PINB,tlacitko
	rcall interierNESTISK
	sbis  PINB,tlacitko   	;hlida zda je sepnut dverni kontakt
	rcall interierSTISK	
rjmp  main

;*********
;procedury
;*********
;--------
;interier:
;--------
interierSTISK:	  		     ;zelena ledka//deklarace PWM1
	ldi    pom,0xf0
	eor    pom,citac
	brne   skok
	rcall  svit 		
skok:
	ldi    citac,0xff
ret


interierNESTISK:		     ;sviti plny jas
	ldi    citac,0xf0
	mov    pom,PWM1_poc_pulsu    ;opetovne nastaveni plneho svitu
	out    OCR0A,pom
	ldi    pom, 0b00100011	     ;Fast PWM Mode, out on OC0B, non Inverting
	out    TCCR0A, pom	
ret



svit:			  	     ;5sec (256x256x25 x 3us = 4,92s)
	ldi   pom, 0b00100011	     ;Fast PWM Mode, out on OC0B, non Inverting
	out   TCCR0A, pom	
	mov   pom,PWM1_poc_pulsu
	out   OCR0A,pom 	

;5sec plny svit	
	clr r1					
	clr r2					
	ldi r18,25
wait:
	inc r1					;256x
	brne wait
	inc r2					;256x256
	brne wait
	dec r18					;256x256x25
	brne wait 

;2sec dosvit
    ldi pom,50
	mov r1,pom
	clr r2
hop: 
;dekrementace
;------------  
    mov pom, PWM1_poc_pulsu
	inc r2
	add pom,r2
	out OCR0A,pom	
;------------
	rcall smallwait
 	dec r1
brne hop

	ldi  pom,0b00000011	  	;odpojeni od PWM
	out  TCCR0A, pom		;odpojeni od PWM		
ret

smallwait:					;255x32
	lds r3,32
	clr r18
back:
	inc r18
brne back
	dec r3
brne back
nop
ret
;---------------------------------------------------------------- 
;prevedeni hodnoty z ADC do intervalu 10 - 100% pro pouziti v PWM
;----------------------------------------------------------------
;Pro zjednoduseni pocitani je max hodnota PWM 36. Kdyz max hodnota z AD je 255, pak po
;vydeleni 8 (odstranena des. cast) je to rovno 31. Kdyz pricteme 4, tak 35, tzn. maximalni
;strida je 97%, coz jde. Naopak minimalni, tedy v intervalu ADCH od 0 do 7, kdy vysledek 
;je 4, je 11%. Intervaly tedy nejsou presne podle zadani, ale v praxi to je zanedbatelne,
;a usetrilo se hodne pocitani pro dosazeni presne hodnoty ;-) Protoze min hodnota neni 0,
;ale 10% (resp 11%) neni potreba odpojovat vystupni pin od PWM generatoru.

;-------
;palubka:
;-------
ADCconv_compl:
	clr pom				;odstran vysledek posledniho prevodu
;dekodovani hodnoty
	lds pom, ADCH			;hodnotu H bytu z AD prevodu do Temp
	lsr pom				;Hodnota deleno 2x
	lsr pom				;Hodnota deleno 2x
	lsr pom				;Hodnota deleno 2x
					;celkove deleno 8x

	mov PWM2_poc_pulsu, pom	        ;hodnota ADCH/8
	ldi pom, 0x04
	add PWM2_poc_pulsu, pom	        ;pricte 4
	mov pom,PWM2_poc_pulsu
	sts OCR2A, pom			;nastavi PWM pro palubku
reti

Dekódování hodnoty převzato od uživatele: Vafektom

[editovat] Teoreticky připojení SD karty, sériový port, softwarové USB, bootloader. Programování přístupu k vnější RAM a k externě připojeným vstupům a výstupům v jazyku C, odevzdání 2. domácího úkolu v papírové podobě na začátku cvičení.

[editovat] Další možnosti konfigurace AVR procesorů, další typy programátorů AVR, watchdog, BOR. Programování v jazyku C

[editovat] Prezentace výsledků práce, zápočet

http://noel.feld.cvut.cz/vyu/a2m99mam/index.php/U%C5%BEivatel:Vafektom#Semestr.C3.A1ln.C3.AD_pr.C3.A1ce_-_Regul.C3.A1tor_PC_ventil.C3.A1toru_se_zp.C4.9Btnou_vazbou_ze_sign.C3.A1lu_TACHO

Osobní nástroje