EB keyboard

Z MAM wiki

(Rozdíly mezi verzemi)
Přejít na: navigace, hledání
m (Klávesnice)
(Sleep mode, dokončení obsluhy KB)
Řádka 1: Řádka 1:
-
S připojením jednotlivých tlačítek jsme se seznámili při našem [[První pokus v simulátoru AVR|prvním pokusu v simulátoru AVR]], jakmile se množství tlačítek zvětší (6 a více), ušetříme vývody procesoru zapojením tlačítek do matice a jejich postupným souřadnicovým čtením. Klávesnice [[Evaluation Board|vývojové destičky]] má 10 tlačítek S1 až S10 zapojených v neúplné matici 3*4, je tedy připojena 7 vodiči, 3 pro řady a 4 pro sloupce. Pozor, na plošném spoji destičky je uspořádání tlačítek odlišné od schématu, fyzicky jsou v horní vodorovné řadě tlačítka S1, S4 a S7 připojená ke vstupu PC1, druhá řada je S2, S5 a S8 na PC2, třetí řada S3, S6, S9 na PC3, a ve čtvrté řadě je pouze tlačítko S10 připojené jako čtvrté ke vstupu PC2.
+
S připojením jednotlivých tlačítek jsme se seznámili při našem [[První pokus v simulátoru AVR|prvním pokusu v simulátoru AVR]], jakmile se množství tlačítek zvětší (6 a více), ušetříme vývody procesoru zapojením tlačítek do matice a jejich postupným souřadnicovým čtením. Klávesnice [[Evaluation Board|vývojové destičky]] má 10 tlačítek S1 až S10 zapojených v neúplné matici 3*4, je tedy připojena 7 vodiči, 3 pro řady a 4 pro sloupce. Pozor, na plošném spoji destičky je uspořádání tlačítek odlišné od schématu, fyzicky jsou v horní vodorovné řadě tlačítka S1, S4 a S7 připojená ke vstupu PC1, druhá řada je S2, S5 a S8 na PC2, třetí řada S3, S6, S9 na PC3, a ve čtvrté řadě je pouze tlačítko S10 připojené jako čtvrté ke vstupu PC2. Na propojce JP1 je třeba spojit piny 2 a 3.
Řádka 5: Řádka 5:
-
[[Soubor:EB keyboard.png|Klávesnice|600px]]
+
[[Soubor:EB keyboard.png|Klávesnice]]
Obsluha klávesnice je obdobná jako v [[První pokus v simulátoru AVR|prvním pokusu v simulátoru AVR]] s interním pull-up rezistorem na vstupech PC1-PC3, jen nemáme tlačítka připojená druhým koncem přímo k zemi, ale přes diody D1-D10 k výstupním portům PD2-PD5. Pro nalezení, které tlačítko bylo stisknuto, je vždy jenom jeden budicí výstup ve stavu L, všechny ostatní jsou ve třetím stavu (díky diodám mohou být i v H). Která řada je v L periodicky měníme. Vstupy jsou interními pull-up rezistory (měkká jednička) drženy v H. Zachycení stavu L na některém vstupu PC1-PC3 znamená stisknutí tlačítka, jeho souřadnici určuje řada a sloupec, na kterých je nalezena úroveň L. Výstup nakonfigurujeme do třetího stavu přepnutím příslušného bitu registrů DDRD a PORTD do log. 0, tj. na vstup bez pull-up rezistoru.
Obsluha klávesnice je obdobná jako v [[První pokus v simulátoru AVR|prvním pokusu v simulátoru AVR]] s interním pull-up rezistorem na vstupech PC1-PC3, jen nemáme tlačítka připojená druhým koncem přímo k zemi, ale přes diody D1-D10 k výstupním portům PD2-PD5. Pro nalezení, které tlačítko bylo stisknuto, je vždy jenom jeden budicí výstup ve stavu L, všechny ostatní jsou ve třetím stavu (díky diodám mohou být i v H). Která řada je v L periodicky měníme. Vstupy jsou interními pull-up rezistory (měkká jednička) drženy v H. Zachycení stavu L na některém vstupu PC1-PC3 znamená stisknutí tlačítka, jeho souřadnici určuje řada a sloupec, na kterých je nalezena úroveň L. Výstup nakonfigurujeme do třetího stavu přepnutím příslušného bitu registrů DDRD a PORTD do log. 0, tj. na vstup bez pull-up rezistoru.
Řádka 103: Řádka 103:
; Keyboard init:
; Keyboard init:
-
; PC3:1 inputs with pull-ups
+
; PC3:1 all lines are inputs with pull-ups
-
; PD5:2 outputs with log.0
+
; PD5:2 all lines are outputs with log.0
</pre>
</pre>
Řádka 133: Řádka 133:
</pre>
</pre>
-
Obsluha přerušení od klávesnice - bylo zmáčknuto nějaké tlačítko, potřebujeme zjistit jaké a jeho kód zobrazit na displeji
+
Obsluha přerušení od klávesnice - bylo zmáčknuto nějaké tlačítko, potřebujeme zjistit jaké (podprogram KEYPRESS), a jeho kód zobrazit na displeji (podprogram DISPLAY)
<pre>
<pre>
Řádka 141: Řádka 141:
reti ; return from Interrupt
reti ; return from Interrupt
</pre>
</pre>
 +
 +
Zjištění stisknutého tlačítka - log. 0 postupně projde přes všechny výstupy, na ostatních je stav vysoké impedance, pro každou kombinaci postupně testujeme všechny vstupy, zda jsou stále v log. 1. Po nalezení log. 0 je do R16 umístěn kód klávesy a podprogram lze opustit (skok na KEYRET), předtím je ale třeba připravit log. 0 na všechny výstupy, aby bylo zachyceno další zmáčknutí libovolné klávesy. Čtveřici příkazů sbi/cbi jde nahradit pomocí out a maskou pro jednotlivé kombinace, vzhledem k potřebě maskování to vůbec nemusí být efektivnější než 4 instrukce sbi/cbi
 +
 +
<pre>
 +
 +
KEYPRESS:
 +
KEY1:
 +
sbi DDRD, 2 ;output with log. 0 to the row with numbers 1,4,7
 +
cbi DDRD, 3 ;high impedance on rows with numbers other than 1,4,7
 +
cbi DDRD, 4
 +
cbi DDRD, 5
 +
sbic PINC, 1
 +
rjmp KEY4
 +
ldi R16, 0x01 ;key number 1 pressed
 +
rjmp KEYRET ;return from keyboard subroutine
 +
KEY4:
 +
sbic PINC, 2
 +
rjmp KEY7
 +
ldi R16, 0x02
 +
rjmp KEYRET
 +
KEY7: ......
 +
 +
KEY2: ......
 +
 +
</pre>
 +
 +
V mezidobí mezi stisky klávesy nemusí procesor dělat nic užitečného, to ovšem musíme nějak zařídit - např. skok na sebe sama (dost usilovná nepřetržitá činnost), elegantnější a úspornější je přepnutí do některého z módů spánku.
 +
 +
== Mód spánku ==
 +
 +
V módu spánku lze zastavit nebo omezit činnost jednotlivých částí procesoru, podle toho také klesá spotřeba, která je při normálním provozu v závislosti na napájecím napětí a frekvenci řádu jednotek mA, od cca 0,5 mA při taktu 1 MHz a Ucc=2 V do 12 mA při 8 MHz a 5 V, při nejhlubším uspání do Power down módu je typická spotřeba 500 nA. Podrobněji datasheet, Electrical Characteristics.
 +
 +
Módů je 5, viz datasheet, Power Management and Sleep Modes, přepínají se řídicím registrem SMCR, Sleep Mode Control Register
 +
 +
'''Idle mode''' zastaví CPU a nechá běžet SRAM, časovače/čítače, USART, 2-wire Serial Interface, SPI port, a interrupt system.
 +
 +
'''Power-down mode''' chrání obsah registrů, ale zastaví oscilátor, to do následujícího interruptu nebo hardwarového resetu zastaví všechny další funkce.
 +
 +
'''Power-save mode''' nechá v činnosti asynchronní časovače, zbytek součástky je zastaven.
 +
 +
'''ADC Noise Reduction mode''' zastaví CPU a všechny I/O moduly vyjma asynchronního časovače a ADC, aby bylo minimalizováno rušení během A/D převodu.
 +
 +
Ve '''Standby mode''' nadále běží oscilátor, zbytek je uspán, to dovoluje rychlé probuzení a přitom nízkou spotřebu.
 +
 +
 +
<pre>
 +
 +
; 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 ; Idle mode
 +
out SMCR,r16 ; Sleep mode set
 +
 +
 +
; Sleep loop, wake up by the Interrupt, return with RETI back to sleep loop
 +
 +
loop:
 +
sleep ; now AVR sleeps
 +
rjmp loop ; and sleep again - return from Interrupt to this instruction
 +
 +
</pre>
 +
 +
 +
[[Category:Kód v assembleru]]
 +
[[Category:PWM]]

Verze z 11. 3. 2014, 20:41

S připojením jednotlivých tlačítek jsme se seznámili při našem prvním pokusu v simulátoru AVR, jakmile se množství tlačítek zvětší (6 a více), ušetříme vývody procesoru zapojením tlačítek do matice a jejich postupným souřadnicovým čtením. Klávesnice vývojové destičky má 10 tlačítek S1 až S10 zapojených v neúplné matici 3*4, je tedy připojena 7 vodiči, 3 pro řady a 4 pro sloupce. Pozor, na plošném spoji destičky je uspořádání tlačítek odlišné od schématu, fyzicky jsou v horní vodorovné řadě tlačítka S1, S4 a S7 připojená ke vstupu PC1, druhá řada je S2, S5 a S8 na PC2, třetí řada S3, S6, S9 na PC3, a ve čtvrté řadě je pouze tlačítko S10 připojené jako čtvrté ke vstupu PC2. Na propojce JP1 je třeba spojit piny 2 a 3.


Schéma zapojení klávesnice:

Klávesnice

Obsluha klávesnice je obdobná jako v prvním pokusu v simulátoru AVR s interním pull-up rezistorem na vstupech PC1-PC3, jen nemáme tlačítka připojená druhým koncem přímo k zemi, ale přes diody D1-D10 k výstupním portům PD2-PD5. Pro nalezení, které tlačítko bylo stisknuto, je vždy jenom jeden budicí výstup ve stavu L, všechny ostatní jsou ve třetím stavu (díky diodám mohou být i v H). Která řada je v L periodicky měníme. Vstupy jsou interními pull-up rezistory (měkká jednička) drženy v H. Zachycení stavu L na některém vstupu PC1-PC3 znamená stisknutí tlačítka, jeho souřadnici určuje řada a sloupec, na kterých je nalezena úroveň L. Výstup nakonfigurujeme do třetího stavu přepnutím příslušného bitu registrů DDRD a PORTD do log. 0, tj. na vstup bez pull-up rezistoru.

Pro zjištění, že bylo zmáčknuto nějaké tlačítko, můžeme nastavit všechny výstupu PD2-PD5 do log. 0 a hlídat změnu kteréhokoliv vstupu PC1-PC3 do log. 0, teprve když se log. 0 objeví, tak je třeba prohledat celou matici tlačítek klávesnice postupně.


Přerušení

Přerušení vyvolá změnu běhu programu v závislosti na vnějším hardwarovém podnětu. Přerušení lze vyvolat prakticky od všech periferií a mnoha dalšími událostmi, podrobný popis je v sekci Interrupts datasheetu. My v programu využíváme přerušení vyvolané změnou úrovně signálu na klávesnici, každá změna způsobí skok do tabulky interrupt vektorů, umístěné např. od začátku programové paměti, podle typu procesoru je v ní pro každý zdroj přerušení vyhrazeno 1 šestnáctibitové slovo (ATmega48 a 88) nebo 2 slova (ATmega168) pro skok na obsluhu přerušení. Obsluha je zajištěna podprogramem, který končí instrukci reti, návrat z interruptu. Jaké přerušení je povoleno a na co reaguje je třeba nastavit řídicími slovy, konkrétně pro náš případ čtení klávesnice aktivujeme přerušení od 3 bitů PINC, kam máme připojené vstupy pro čtení klávesnice (PC1..PC3), v řídicím registru PCICR přerušení povolujeme přerušení PCINT1 od portu C a v řídicím registru PCMSK1 nastavujeme masku, které bity portu mohou přerušení vyvolat. Přerušení je třeba globálně povolit instrukcí SEI. Pro obsluhu přerušení je nutné mít předem správně nastavený zásobník (stack), ukládají se do něj návratové adresy! Vhodné je nastavit ho na konec RAM, lze využít low(RAMEND) a high(RAMEND) z .INCLUDE "m168Adef.inc".

Úplný seznam vektorů přerušení a jejich možná obsluha pro ATmega168 (pozor, u ATmega88 s menší velikostí paměti se liší, jsou na po sobě bezprostředně následujících adresách, neboť místo skoku JMP na absolutní adresu stačí relativní RJMP, který se vejde do jednoho slova místo JMP ve dvou slovech!):

.org 0x0000 
	jmp RESET ; Reset Handler
.org 0x0002 
	jmp EXT_INT0 ; IRQ0 Handler
.org 0x0004 
	jmp EXT_INT1 ; IRQ1 Handler
.org 0x0006 
	jmp PCINT0 ; PCINT0 Handler
.org 0x0008 
	jmp PCINT1 ; PCINT1 Handler
.org 0x000A 
	jmp PCINT2 ; PCINT2 Handler
.org 0x000C 
	jmp WDT ; Watchdog Timer Handler
.org 0x000E 
	jmp TIM2_COMPA ; Timer2 Compare A Handler
.org 0x0010 
	jmp TIM2_COMPB ; Timer2 Compare B Handler
.org 0x0012 
	jmp TIM2_OVF ; Timer2 Overflow Handler
.org 0x0014 
	jmp TIM1_CAPT ; Timer1 Capture Handler
.org 0x0016 
	jmp TIM1_COMPA ; Timer1 Compare A Handler
.org 0x0018 
	jmp TIM1_COMPB ; Timer1 Compare B Handler
.org 0x001A 
	jmp TIM1_OVF ; Timer1 Overflow Handler
.org 0x001C 
	jmp TIM0_COMPA ; Timer0 Compare A Handler
.org 0x001E 
	jmp TIM0_COMPB ; Timer0 Compare B Handler
.org 0x0020 
	jmp TIM0_OVF ; Timer0 Overflow Handler
.org 0x0022 
	jmp SPI_STC ; SPI Transfer Complete Handler
.org 0x0024 
	jmp USART_RXC ; USART, RX Complete Handler
.org 0x0026 
	jmp USART_UDRE ; USART, UDR Empty Handler
.org 0x0028 
	jmp USART_TXC ; USART, TX Complete Handler
.org 0x002A 
	jmp ADCon ; ADC Conversion Complete Handler
.org 0x002C 
	jmp EE_RDY ; EEPROM Ready Handler
.org 0x002E 
	jmp ANA_COMP ; Analog Comparator Handler
.org 0x0030 
	jmp TWI ; 2-wire Serial Interface Handler
.org 0x0032 
	jmp SPM_RDY ; Store Program Memory Ready Handler


Užitečné fragmenty programu pro obsluhu klávesnice:


.INCLUDE "m168def.inc"


.ORG 0x0000 
	jmp Main ; Reset Handler

.ORG 0x0008 
	jmp isr1 ; PCINT1 Handler



; Main program start

Main: 

; Stack pointer init:
	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:
; PC3:1 all lines are inputs with pull-ups
; PD5:2 all lines are outputs with log.0

Nastavení řídicích slov pro vyvolání přerušení

; 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
;
; X - alias for 16-bit register created from two 8-bit registers R27, R26

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

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

	sei ; Enable interrupts

Obsluha přerušení od klávesnice - bylo zmáčknuto nějaké tlačítko, potřebujeme zjistit jaké (podprogram KEYPRESS), a jeho kód zobrazit na displeji (podprogram DISPLAY)

isr1:
	rcall KEYPRESS
	rcall DISPLAY
	reti ; return from Interrupt

Zjištění stisknutého tlačítka - log. 0 postupně projde přes všechny výstupy, na ostatních je stav vysoké impedance, pro každou kombinaci postupně testujeme všechny vstupy, zda jsou stále v log. 1. Po nalezení log. 0 je do R16 umístěn kód klávesy a podprogram lze opustit (skok na KEYRET), předtím je ale třeba připravit log. 0 na všechny výstupy, aby bylo zachyceno další zmáčknutí libovolné klávesy. Čtveřici příkazů sbi/cbi jde nahradit pomocí out a maskou pro jednotlivé kombinace, vzhledem k potřebě maskování to vůbec nemusí být efektivnější než 4 instrukce sbi/cbi


KEYPRESS:
KEY1:
	sbi 	DDRD, 2	;output with log. 0 to the row with numbers 1,4,7	
	cbi 	DDRD, 3	;high impedance on rows with numbers other than 1,4,7	
	cbi 	DDRD, 4
	cbi 	DDRD, 5
	sbic	PINC, 1
	rjmp	KEY4
	ldi	R16, 0x01	;key number 1 pressed
	rjmp	KEYRET	;return from keyboard subroutine
KEY4:
	sbic	PINC, 2
	rjmp	KEY7
	ldi	R16, 0x02
	rjmp	KEYRET
KEY7:	......

KEY2:	......

V mezidobí mezi stisky klávesy nemusí procesor dělat nic užitečného, to ovšem musíme nějak zařídit - např. skok na sebe sama (dost usilovná nepřetržitá činnost), elegantnější a úspornější je přepnutí do některého z módů spánku.

Mód spánku

V módu spánku lze zastavit nebo omezit činnost jednotlivých částí procesoru, podle toho také klesá spotřeba, která je při normálním provozu v závislosti na napájecím napětí a frekvenci řádu jednotek mA, od cca 0,5 mA při taktu 1 MHz a Ucc=2 V do 12 mA při 8 MHz a 5 V, při nejhlubším uspání do Power down módu je typická spotřeba 500 nA. Podrobněji datasheet, Electrical Characteristics.

Módů je 5, viz datasheet, Power Management and Sleep Modes, přepínají se řídicím registrem SMCR, Sleep Mode Control Register

Idle mode zastaví CPU a nechá běžet SRAM, časovače/čítače, USART, 2-wire Serial Interface, SPI port, a interrupt system.

Power-down mode chrání obsah registrů, ale zastaví oscilátor, to do následujícího interruptu nebo hardwarového resetu zastaví všechny další funkce.

Power-save mode nechá v činnosti asynchronní časovače, zbytek součástky je zastaven.

ADC Noise Reduction mode zastaví CPU a všechny I/O moduly vyjma asynchronního časovače a ADC, aby bylo minimalizováno rušení během A/D převodu.

Ve Standby mode nadále běží oscilátor, zbytek je uspán, to dovoluje rychlé probuzení a přitom nízkou spotřebu.



; 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 ; Idle mode 
	out SMCR,r16 ; Sleep mode set


; Sleep loop, wake up by the Interrupt, return with RETI back to sleep loop

loop:
	sleep ; now AVR sleeps
	rjmp loop ; and sleep again - return from Interrupt to this instruction

Osobní nástroje