Uživatel:Vlachja5

Z MAM wiki

(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
Řádka 1: Řádka 1:
-
Cvičení 6 - větrák s přerušením, časovačem v modu Fast PWM a klávesnicí se třetím stavem.
+
 
 +
== Cvičení 6 ==
 +
- větrák s přerušením, časovačem v modu Fast PWM a klávesnicí se třetím stavem.
 +
 
<pre>
<pre>

Verze z 27. 3. 2013, 20:08

Cvičení 6

- větrák s přerušením, časovačem v modu Fast PWM a klávesnicí se třetím stavem.


; Soubor ze cvičení k regilaci otáček s detailnějšími komentáři a upraven
; s klávesnicí ve třetím stavu pro eliminaci problému se stisknutím více tlačítek najednou


.INCLUDE "m168def.inc"

.EQU PWM_PULSES = 36	; value for 27.8 kHz PWM
;.EQU PWM_PULSES = 45	; value for 22.2 kHz PWM


.ORG 0x0000 
	jmp Main ; Při resetu (odpovídá vekt. 0000) skoč na Main

.ORG 0x0008 
	jmp isr1 ; Při změně pinu (vektor 0008 - u každého AVR jinak!, definice konkrétního pinu níže) skož na isr1

Main: 

	ldi r16,high(RAMEND); Main program start
	out SPH,r16 ; Set Stack Pointer to top of RAM
	ldi r16,low(RAMEND)
	out SPL,r16


; Hardware initialization

; Keyboard init:
	cbi DDRC, 2 ; Sloupce klávesnice jako vstupy (jen tři - písmena netřeba)
	cbi DDRC, 3
	cbi DDRC, 4

	sbi PORTC, 2 ; nastavení měkkých jedniček na vstupy sloupců klávesnice - pull up odpory
	sbi PORTC, 3
	sbi PORTC, 4

	cbi DDRD, 0 ; následujících 8 řádků nastaví řádky klávesnice do třetího stavu
	cbi DDRD, 1 ; 
	cbi DDRD, 2
	cbi DDRD, 3

	cbi PORTD, 0	
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3


; Timer controlled PWM init:
;
; There are registers TCCR0A and TCCR0B for config, DDRD for output bit
; enabling, OCR0A for counter lenght and OCR0A for pulse "high" lenght.
; Register TIMSK0 controlls interrupts - not used, 0x00 by default 

PWM_INIT:
	ldi R17, 0b00100011	; Nastavení 1. řídicího registru čítače, poslední dva bity nastavují mód čítače (v tomto případě Fast PWM kdy vrchní hodnota čítání bude v registru OCR0A - pozor! O módu rozhoduje také bit 3 v registru TCCR0B!), první čtyři bity nastavují, jak se čítač chová při dosažení porovnávací úrovně (v tomto případě nastaví na pinu OC0B jedničku když má čítač menší hodnotu než OCR0B a naopak)   
	out TCCR0A, R17			; 
	ldi R17, 0b00001001	; nastavení módu viz přechozí komentář, čítání bez předděličky
	out TCCR0B, R17
	ldi R17, PWM_PULSES	; Čítač přeteče při dosažení hodnoty v prom. PWM_PULSES, tzn PWM na frekvenci  frekv. oscil/PWM_PULSES. Změnou OCR0B pak budu měnit střídu PWM
	out OCR0A, R17   		

	sbi DDRD, 5	; Čítač sdílí svůj výstup OC0B s 5. pinem na portu D, musím tedy nastavit jako výstup


; Keyboard interrupt setup
;
; 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


;PCICR je registr nastavující na posledních třech bitech jeden jaký ze tří možných vektorů přerušení pro změnu na pinu budou aktivní
	ldi r26, PCICR ; R26 a 27 tvoří 16bit registr X. Do spodních 8 bitů dám adresu PCICR
	clr r27 ; Hořejšek registru X vymažu
	ldi r16,0b00000010 ; do R 16 si připravim požadované nastavení - v tomto případě PCINT1 - vektor 0008 viz začátek programu
	st X, r16 ; Uložim do X nastavení přerušení - tím nastavim registr PCICR

;PCMSK1 mi určuje piny, které budou způsobovat přerušení PCINT1, stejným způsobem nastavím jako předchozí
	ldi r26, PCMSK1
	clr r27
	ldi r16,0b00011100 ; Přerušení budou způsobovat piny PCINT10, PCINT11 a PCINT12, které mají stejné vývody jako piny 2,3,4 na portu C - to jsou naše slouce klávesnice s pullup odpory
	st X, r16

	sei ; zapnutí přerušení: mělo by být ekvivalentní sbi SREG,7


; Set sleep mode of the CPU
; SMCR: 0,0,0,0,SM2,SM1,SM0,SE   SM2..0: Sleep Mode Select Bits, SE: Sleep enabled)

	ldi r16,0b00000001 ; Aktivace Sleep módu - při provedení instukce sleep skutečně proc usne
	out SMCR,r16 ; Zápis do příslušného registru


; Procesor bude spát dokud nezmáčknu klávesu a nezpůsobim přerušení

loop:
	sleep 
	nop 
	rjmp loop


; PCINT0 Service Routine:
;
; To do: *** rpm reading, regulation, etc.


isr1:	;obsluha přerušení při zmáčknutí klávesy
	rcall KEYPRESS

	mov R17, R16
	lsl R17		; posun vlevo - v bináru násobení dvěmi
	lsl R17		; ještě jednou - takže dohromady 4, maximální hodnota při stisku 9 je tedy 36
	out OCR0B, R17  ; uložim číslo 0 ... 36 v (10 kroků, tlačítek) do porovnávacího registru k nastavení střídy

	reti ; návrat z přerušení na poslední adresu před přerušením +1 (při reti se narozdíl od ret neukládá stavový registr, je nutno to udělat růčo)


; Keyboard decoding:

KEYPRESS:
KEY0:		;kontrola stistku nuly - po úpravě 
	cbi		DDRD,0
	cbi 	PORTD, 0
	cbi		DDRD,1
	cbi 	PORTD, 1
	cbi		DDRD,2
	cbi 	PORTD, 2	; řádky které nekontroluji tak nastavím do třetího stavu, tj jako vstupy bez pullup
	
	sbi		DDRD,3		; řádek odpovádající kontrolované klávese jako výstup do nuly
	cbi 	PORTD, 3	
	
	sbic	PINC, 3		; v případě že je kontrolovaná klávesa, a tedy je na PINC sražená měkká 1 na 0, přeskočim následující instrukci
	rjmp	KEY1		; skok na test další klávesy
	ldi		R16, 0		; do uživ. registru šoupnu zmáčknutou hodnotu (v tomto případě nulu) kterou pak vhodně navhájuju, vložim do komparační
	rjmp	KEYRET
KEY1:
	sbi		DDRD,0		; nulu na první řádek, testuju jedničku
	cbi 	PORTD, 0	
	
	cbi		DDRD,1		; třetí stav na ost. řádcích
	cbi 	PORTD, 1
	cbi		DDRD,2	
	cbi 	PORTD, 2
	cbi		DDRD,3
	cbi 	PORTD, 3
		
	sbic	PINC, 2
	rjmp	KEY2
	ldi		R16, 1		; pressed key 1
	rjmp	KEYRET
KEY2:
	sbic	PINC, 3
	rjmp	KEY3
	ldi		R16, 2
	rjmp	KEYRET
KEY3:
	sbic	PINC, 4
	rjmp	KEY4
	ldi		R16, 3
	rjmp	KEYRET

KEY4:
	cbi		DDRD,0		
	cbi 	PORTD, 0
	
	sbi		DDRD,1
	cbi 	PORTD, 1	; log. 0 to the row with 4, 5, 6, B
	
	cbi		DDRD,2
	cbi 	PORTD, 2
	cbi		DDRD,3
	cbi 	PORTD, 3
		
	sbic	PINC, 2
	rjmp	KEY5
	ldi		R16, 4		; pressed key 4
	rjmp	KEYRET
KEY5:
	sbic	PINC, 3
	rjmp	KEY6
	ldi		R16, 5
	rjmp	KEYRET
KEY6:
	sbic	PINC, 4
	rjmp	KEY7
	ldi		R16, 6
	rjmp	KEYRET

KEY7:
	cbi		DDRD,0		
	cbi 	PORTD, 0
	cbi		DDRD,1		
	cbi 	PORTD, 1

	sbi		DDRD,2
	cbi 	PORTD, 2	
	
	cbi		DDRD,3
	cbi 	PORTD, 3

	sbic	PINC, 2
	rjmp	KEY8
	ldi		R16, 7		;pressed key 7
	rjmp	KEYRET
KEY8:
	sbic	PINC, 3
	rjmp	KEY9
	ldi		R16, 8
	rjmp	KEYRET
KEY9:
	sbic	PINC, 4
	rjmp	KEYRET
	ldi		R16, 9

KEYRET:
	cbi DDRD, 0 ; následujících 8 řádků nastaví řádky klávesnice do třetího stavu
	cbi DDRD, 1 ; 
	cbi DDRD, 2
	cbi DDRD, 3

	cbi PORTD, 0	
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3
	ret				; návrat na adresu uloženou na vršku zásobníku - adresa posledního volání podprogramu +1
Osobní nástroje