Uživatel:Vlachja5

Z MAM wiki

(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
(Stránka vyprázdněna)
Řádka 1: Řádka 1:
 +
; 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

Verze z 27. 3. 2013, 20:01

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