Uživatel:Krctomas
Z MAM wiki
(Rozdíly mezi verzemi)
m |
|||
(Nejsou zobrazeny 4 mezilehlé verze.) | |||
Řádka 1: | Řádka 1: | ||
Spolupráce s [[Uživatel:Korbeljir|Jiřím Korbelem]] a [[Uživatel:Kovaron3|Ondřejem Kovářem]]. | Spolupráce s [[Uživatel:Korbeljir|Jiřím Korbelem]] a [[Uživatel:Kovaron3|Ondřejem Kovářem]]. | ||
- | == Cvičení 4 == | + | == Cvičení 4 - LED diody== |
'''ATtiny 2313''' - Při stisku tlačítka 1 svítí červená LED, jinak zelená | '''ATtiny 2313''' - Při stisku tlačítka 1 svítí červená LED, jinak zelená | ||
Řádka 103: | Řádka 103: | ||
</pre> | </pre> | ||
- | == Cvičení 5 == | + | == Cvičení 5 - Jednoduchá PWM== |
'''ATmega88''' - Při stisku tlačítka 0-7 se větrák roztočí s rychlostí odpovídající 8 stupňové PWM. (Resp. prvních pár rychlostí bude zřejmě příliš malých, aby se větrák vůbec roztočil.) | '''ATmega88''' - Při stisku tlačítka 0-7 se větrák roztočí s rychlostí odpovídající 8 stupňové PWM. (Resp. prvních pár rychlostí bude zřejmě příliš malých, aby se větrák vůbec roztočil.) | ||
Řádka 310: | Řádka 310: | ||
</pre> | </pre> | ||
- | == Cvičení 6+7 == | + | == Cvičení 6+7 - PWM s interruptem== |
- | '''Atmega88''' - PWM s klavesnici 0-9, po stisku 0 se větrák zastaví. | + | '''Atmega88''' - PWM s klavesnici 0-9, po stisku 0 se větrák zastaví. Po stisku 1-9 by nejdříve měl větrák fučet asi na 50% po 0,25''s'', pak teprve nastane PWM. |
<pre> | <pre> | ||
; | ; | ||
Řádka 321: | Řádka 321: | ||
; Fan starts to rotate with the first valid key press | ; Fan starts to rotate with the first valid key press | ||
; | ; | ||
- | ; When zero is pressed, fan stops | + | ; *When zero is pressed, fan stops |
; | ; | ||
; To do: *** Catch only the key press, not key release | ; To do: *** Catch only the key press, not key release | ||
; | ; | ||
- | ; | + | ; *Done: *** Set higher value of PWM (=higher fan rpm) for |
; a few first periods to start the fan reliably | ; a few first periods to start the fan reliably | ||
; | ; | ||
Řádka 335: | Řádka 335: | ||
- | .INCLUDE " | + | .INCLUDE "m88def.inc" |
.EQU PWM_PULSES = 36 ; value for 27.8 kHz PWM | .EQU PWM_PULSES = 36 ; value for 27.8 kHz PWM | ||
Řádka 439: | Řádka 439: | ||
isr1: | isr1: | ||
+ | |||
rcall KEYPRESS | rcall KEYPRESS | ||
+ | |||
+ | cpi R16,0 ; Tyhle dva radky spousti funkci pro vetsi (50%) rychlost priblizne po 0,25s | ||
+ | brne Zacatek ; (pokud samozrejme neni stisknuta 0, pak by to nemelo smysl) | ||
+ | ; Pokud nefunguji, zakomentovat. (Nevidim ale duvod, na simulaci to vypada dobre) | ||
mov R17, R16 | mov R17, R16 | ||
Řádka 446: | Řádka 451: | ||
out OCR0B, R17 ; output pulse "high" lenght to PWM compare unit | out OCR0B, R17 ; output pulse "high" lenght to PWM compare unit | ||
- | + | rjmp isr1 ; return from Interrupt | |
+ | |||
+ | |||
+ | |||
+ | Zacatek: ; Po stisku pusti 50% rychlost | ||
+ | ldi R20, PWM_PULSES | ||
+ | mov R21, R20 | ||
+ | lsr R21 ; Vydeleni PWM_PULSES dvema, tedy polovicni nez maximalni rychlost | ||
+ | out OCR0B, R21 ; Polovicni rychlost na vystup | ||
+ | clr R20 | ||
+ | clr R21 | ||
+ | ldi R22, 2 | ||
+ | Zacatek1: ; Doba zhruba 0,25s, po kterou bude na vystupu polovicni rychlost | ||
+ | inc R20 | ||
+ | brne Zacatek1 | ||
+ | inc R21 | ||
+ | brne Zacatek1 | ||
+ | dec R22 | ||
+ | brne Zacatek1 | ||
+ | ret | ||
Řádka 538: | Řádka 562: | ||
ret | ret | ||
</pre> | </pre> | ||
+ | |||
+ | == Cvičení 8 - Registr + Sedmisegmentovka== | ||
+ | '''ATmega88''' - Posuvný registr a sedmisegmentovka se změnou čísla při stisku jedničky na klávesnici. | ||
+ | <pre> | ||
+ | .INCLUDE "m88def.inc" | ||
+ | |||
+ | .ORG 0x0000 | ||
+ | rjmp Main ; Reset Handler | ||
+ | |||
+ | .ORG 0x0004 | ||
+ | rjmp interrupt ; ovladani preruseni | ||
+ | |||
+ | |||
+ | Main: | ||
+ | |||
+ | ;inicializace portu pro rizeni | ||
+ | ldi R16, 0b00001111 ; nastaveni vystupu | ||
+ | out DDRD, R16 | ||
+ | sbi PORTD, 3 | ||
+ | |||
+ | sbi DDRC, 5 ;vstup pro klavesnici, klavesu 1 | ||
+ | sbi PORTC, 5 | ||
+ | |||
+ | ldi r16,0b00000001 ; Idle mode | ||
+ | out SMCR,r16 ; Sleep mode set | ||
+ | |||
+ | ldi r26, PCICR ; load address of PCICR in Y low | ||
+ | clr r27 ; load high byte with 0 | ||
+ | ldi r16,0b0000010 ; activate PCINT1 | ||
+ | st X, r16 ; store new PCINT1 | ||
+ | |||
+ | ldi r26, PCMSK1 ; load address of PCMSK1 in Y low | ||
+ | clr r27 ; load high byte with 0 | ||
+ | ldi r16,0b00100000 ; allow pin change interrupt on portC bit 5 | ||
+ | st X, r16 ; store new PCMSK1 | ||
+ | |||
+ | sei ; Enable interrupts | ||
+ | |||
+ | spi: | ||
+ | sleep | ||
+ | nop | ||
+ | rjmp spi | ||
+ | |||
+ | |||
+ | interrupt: | ||
+ | ; sbic PORTC, 5 | ||
+ | ; rjmp interrupt | ||
+ | sbic PORTC, 4 | ||
+ | rjmp znak1 | ||
+ | sbis PORTC, 4 | ||
+ | rjmp znak2 | ||
+ | reti | ||
+ | |||
+ | |||
+ | |||
+ | znak1: | ||
+ | cbi PORTD, 0 ;0 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 0 ;1 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | cbi PORTD, 0 ;0 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;0 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 0 ;1 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | cbi PORTD, 0 ;0 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;0 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;0 | ||
+ | cbi PORTD, 2 | ||
+ | cbi PORTC, 4 | ||
+ | ret | ||
+ | |||
+ | znak2: | ||
+ | sbi PORTD, 0 ;1 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | cbi PORTD, 0 ;0 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 0 ;1 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;1 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;1 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;1 | ||
+ | cbi PORTD, 2 | ||
+ | cbi PORTD, 0 ;0 | ||
+ | sbi PORTD, 2 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTD, 2 ;0 | ||
+ | cbi PORTD, 2 | ||
+ | sbi PORTC, 4 | ||
+ | ret | ||
+ | </pre> | ||
+ | |||
+ | == Domácí cvičení 1 - PWM == | ||
+ | |||
+ | <pre> | ||
+ | .INCLUDE "m88def.inc" | ||
+ | |||
+ | .EQU PWM_PULSES = 36 | ||
+ | .EQU PWM_PULSES2 = 255 | ||
+ | |||
+ | .ORG 0x0000 | ||
+ | rjmp Main ; Reset Handler | ||
+ | |||
+ | .ORG 0x0008 | ||
+ | rjmp isr1 ; PCINT1 Handler | ||
+ | |||
+ | 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 | ||
+ | |||
+ | ;;;;;;;;;;; Klavesnice ;;;;;;;;;;; | ||
+ | cbi DDRC, 2 ; set inputs for keyboard (COL1-3) | ||
+ | sbi PORTC, 2 ; set internal Pull-Ups for keyboard | ||
+ | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
+ | |||
+ | |||
+ | PWM_INIT: | ||
+ | ldi R17, 0b00100011 ; Fast PWM Mode, out on OC0B, non Inverting | ||
+ | out TCCR0A, R17 | ||
+ | sts TCCR2A, R17 | ||
+ | ldi R17, 0b00001001 ; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1) | ||
+ | out TCCR0B, R17 | ||
+ | sts TCCR2B, R17 | ||
+ | ldi R17, PWM_PULSES ; load number of clock pulses for 1 PWM period | ||
+ | out OCR0A, R17 | ||
+ | ldi R17, PWM_PULSES2; load number of clock pulses for 1 PWM period | ||
+ | sts OCR2A, R17 | ||
+ | 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 r26, PCMSK1 ; load address of PCMSK1 in Y low | ||
+ | clr r27 ; load high byte with 0 | ||
+ | ldi r16,0b00000100 ; allow pin change interrupt on portC bits 2,3,4 | ||
+ | st X, r16 ; store new PCMSK1 | ||
+ | |||
+ | ;;;;;;;;;;; Vystupy ;;;;;;;;;;; | ||
+ | sbi DDRD, 5 ; PWM 1 - PD5 | ||
+ | sbi DDRD, 3 ; PWM 2 - PD3 | ||
+ | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
+ | |||
+ | ADC_init: | ||
+ | ldi r16,0b10000011 ; Enable ADC system clk/8 | ||
+ | sts ADCSRA,r16 | ||
+ | ldi r16,0b01100000 ; Input PC0 selected and Vcc as reference and data left alignment | ||
+ | sts ADMUX,r16 | ||
+ | ldi r16,0b00000000 ; Free running mode | ||
+ | sts ADCSRB,r16 | ||
+ | ldi r16,0b00000001 ; Digital input ADC0 disable | ||
+ | sts DIDR0,r16 | ||
+ | sei | ||
+ | |||
+ | loop: | ||
+ | rjmp ADC_start | ||
+ | lds r16,ADCSRA ; nacteni konfigurace z ADC | ||
+ | sbrs r16,(ADIF) ; kontrola hotoveho prevodu | ||
+ | rjmp loop | ||
+ | lds r16,ADCH | ||
+ | sts OCR2B, r16 ; nastaveni hodnoty pro druhou PWM | ||
+ | rjmp loop | ||
+ | |||
+ | ADC_start: | ||
+ | lds r16,ADCSRA | ||
+ | ori r16,0b01000000 ; Start conversion | ||
+ | sts ADCSRA,r16 | ||
+ | ret | ||
+ | |||
+ | isr1: | ||
+ | rcall klavesa | ||
+ | ldi r24, 0x2F ; nastaveni pocatecni hodnoty | ||
+ | loop2: | ||
+ | subi r24, 0x01 ; zmenseni o 1 | ||
+ | out OCR0B, r24 | ||
+ | rjmp WAIT | ||
+ | cpi r24,0 | ||
+ | brne loop2 | ||
+ | reti ; return from Interrupt | ||
+ | |||
+ | klavesa: | ||
+ | ldi r16,36 | ||
+ | out OCR0B, R16 ; nastaveni hodnoty do citace | ||
+ | sbic PINC, 2 ; testovani zmackleho tlacitka | ||
+ | ret | ||
+ | rjmp klavesa | ||
+ | |||
+ | WAIT: | ||
+ | ldi R16, 4 | ||
+ | WAIT1: | ||
+ | inc R1 | ||
+ | brne WAIT1 | ||
+ | inc R2 | ||
+ | brne WAIT1 | ||
+ | dec R16 | ||
+ | brne WAIT1 | ||
+ | ret | ||
+ | </pre> | ||
+ | |||
+ | ==Semestrální práce== | ||
+ | viz: [[Jiří Korbel, Ondřej Kovář, Tomáš Krč: Elektronický vrátný]] |
Aktuální verze z 15. 5. 2013, 20:31
Spolupráce s Jiřím Korbelem a Ondřejem Kovářem.
Obsah |
[editovat] Cvičení 4 - LED diody
ATtiny 2313 - Při stisku tlačítka 1 svítí červená LED, jinak zelená
; ; 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 PINB = $16 .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 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 SBI DDRD, 4 SBI PORTB, 2 GO: RCALL COLOR1 RCALL WAIT SBIS PINB, 2 RJMP GOP RCALL WAIT RJMP GO GOP: RCALL COLOR2 SBIC PINB, 2 RJMP GO RJMP GOP ;;; ;;; ;;; P R O C E D U R E S ;;; ;;; SMALLWAIT: LDI R16, 100 SMALLWAIT1: INC R1 ; INC - Increment BRNE SMALLWAIT1 ; BRNE - Branch if Not Equal (Z flag) DEC R16 BRNE WAIT1 RET ; RET - Return from Subroutine WAIT: LDI R16, 4 ; LDI - Load Immediate WAIT1: INC R1 ; Bezi az do R1=255, dalsi krok - preteceni, R1=0 BRNE WAIT1 ; Pokud v R1 neni 0, skoc na 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 RET DARK: CBI PORTB, LED_X CBI PORTB, LED_Y RET
[editovat] Cvičení 5 - Jednoduchá PWM
ATmega88 - Při stisku tlačítka 0-7 se větrák roztočí s rychlostí odpovídající 8 stupňové PWM. (Resp. prvních pár rychlostí bude zřejmě příliš malých, aby se větrák vůbec roztočil.)
;; ; 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 numbers 0-7 ; Keyboard: Rows PD0 to PD3, columns PC1 to PC3 .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 "m168def.inc" ; replaces previous lines of the program .EQU FAN = 2 ; Pin driving FAN is set as output: SBI DDRB, FAN ; Init: RCALL FAN_OFF ; Keyboard init: CBI DDRC, 2 ; CBI DDRC, 3 CBI DDRC, 4 SBI PORTC, 2 ; set internal Pull-Ups for keyboard SBI PORTC, 3 SBI PORTC, 4 SBI DDRD, 0 SBI DDRD, 1 SBI DDRD, 2 SBI DDRD, 3 CBI PORTD, 0 CBI PORTD, 1 CBI PORTD, 2 CBI PORTD, 3 GO: SBIS PINC,2 RCALL PWM ; Simple PWM control of the FAN, if the key is pressed SBIS PINC,3 RCALL PWM SBIS PINC,4 RCALL PWM RJMP GO ;;; ;;; ;;; P R O C E D U R E S ;;; ;;; KEYPRESS: KEY0: SBI PORTD, 0 SBI PORTD, 1 SBI PORTD, 2 CBI PORTD, 3 ;log. 0 to the row with *, 0, #, D SBIC PINC, 3 RJMP KEY1 LDI R16, 0 ;pressed key 0 RJMP KEYRET KEY1: CBI PORTD, 0 ;log. 0 to the row with 1, 2, 3, A SBI PORTD, 1 ;log. 1 on another three SBI PORTD, 2 SBI 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: SBI PORTD, 0 CBI PORTD, 1 ;log. 0 to the row with 4, 5, 6, B SBI PORTD, 2 SBI 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: SBI PORTD, 0 SBI PORTD, 1 CBI PORTD, 2 ;log. 0 to the row with 7, 8, 9, C SBI PORTD, 3 SBIC PINC, 2 RJMP KEYRET LDI R16, 7 ;pressed key 7 KEYRET: CBI PORTD, 0 ; log. 0 on all rows for next key press catch CBI PORTD, 1 CBI PORTD, 2 CBI PORTD, 3 RET VERYSMALLWAIT: LDI R20, 0xFC MOV R1, R20 SMALLWAIT: INC R1 BRNE SMALLWAIT RET WAIT: LDI R21, 4 WAIT1: INC R1 BRNE WAIT1 INC R2 BRNE WAIT1 DEC R21 BRNE WAIT1 RET FAN_ON: SBI PORTB, FAN RET FAN_OFF: CBI PORTB, FAN RET FAN3W: LDI R16, 0x20 FAN3X: RCALL FAN_ON RCALL VERYSMALLWAIT ; pulse ratio controlled by number of waits RCALL VERYSMALLWAIT ; 4:1 in this case RCALL VERYSMALLWAIT RCALL VERYSMALLWAIT RCALL FAN_OFF RCALL VERYSMALLWAIT INC R2 BRNE FAN3X DEC R16 BRNE FAN3X 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
[editovat] Cvičení 6+7 - PWM s interruptem
Atmega88 - PWM s klavesnici 0-9, po stisku 0 se větrák zastaví. Po stisku 1-9 by nejdříve měl větrák fučet asi na 50% po 0,25s, pak teprve nastane PWM.
; ; example fan program for ATmega88 with Timer controlled PWM&Interrupt&Sleep ; ; Rotation speed is controlled by keyboard, ; keys 0-9 represent the speed between 0 and 100 % ; ; Fan starts to rotate with the first valid key press ; ; *When zero is pressed, fan stops ; ; To do: *** Catch only the key press, not key release ; ; *Done: *** Set higher value of PWM (=higher fan rpm) for ; a few first periods to start the fan reliably ; ; ; P4 CPU fan Ucc pin is supposed to be connected ; to +15 V, GND pin is supposed to be connected ; to NMOS Drain,, Source on GND, Gate on ; pin 11 (OC0B, PD5). Fan runs when pin 11 is high. .INCLUDE "m88def.inc" .EQU PWM_PULSES = 36 ; value for 27.8 kHz PWM ;.EQU PWM_PULSES = 45 ; value for 22.2 kHz PWM .ORG 0x0000 rjmp Main ; Reset Handler .ORG 0x0008 rjmp 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: cbi DDRC, 2 ; set inputs for keyboard (COL1-3) cbi DDRC, 3 cbi DDRC, 4 sbi PORTC, 2 ; set internal Pull-Ups for keyboard sbi PORTC, 3 sbi PORTC, 4 sbi DDRD, 0 ; set driving outputs for keyboard sbi DDRD, 1 ; (ROW1-ROW4) sbi DDRD, 2 sbi DDRD, 3 cbi PORTD, 0 ; log. 0 on all rows 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 ; 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, 5 ; set pin 11 as PWM output OC0B (PD5 pin) ; 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 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 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 ; 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 nop ; return from Interrupt to this instruction rjmp loop ; and sleep again ; PCINT0 Service Routine: ; ; To do: *** rpm reading, regulation, etc. isr1: rcall KEYPRESS cpi R16,0 ; Tyhle dva radky spousti funkci pro vetsi (50%) rychlost priblizne po 0,25s brne Zacatek ; (pokud samozrejme neni stisknuta 0, pak by to nemelo smysl) ; Pokud nefunguji, zakomentovat. (Nevidim ale duvod, na simulaci to vypada dobre) mov R17, R16 lsl R17 lsl R17 ; multiply key number by 4 for 10 steps in 40 clock pulses of PWM out OCR0B, R17 ; output pulse "high" lenght to PWM compare unit rjmp isr1 ; return from Interrupt Zacatek: ; Po stisku pusti 50% rychlost ldi R20, PWM_PULSES mov R21, R20 lsr R21 ; Vydeleni PWM_PULSES dvema, tedy polovicni nez maximalni rychlost out OCR0B, R21 ; Polovicni rychlost na vystup clr R20 clr R21 ldi R22, 2 Zacatek1: ; Doba zhruba 0,25s, po kterou bude na vystupu polovicni rychlost inc R20 brne Zacatek1 inc R21 brne Zacatek1 dec R22 brne Zacatek1 ret ; Keyboard decoding: KEYPRESS: KEY0: sbi PORTD, 0 sbi PORTD, 1 sbi PORTD, 2 cbi PORTD, 3 ;log. 0 to the row with *, 0, #, D sbic PINC, 3 rjmp KEY1 ldi R16, 0 ;pressed key 0 ldi R17, 0b00000011 ;Po zapsani R17 do TCCR0A odpojim OCR0B od vystupu, tedy tvrda nula rjmp KEYRET KEY1: cbi PORTD, 0 ;log. 0 to the row with 1, 2, 3, A sbi PORTD, 1 ;log. 1 on another three sbi PORTD, 2 sbi PORTD, 3 sbic PINC, 2 rjmp KEY2 ldi R16, 1 ;pressed key 1 ldi R17, 0b00100011 ;Klasicky R17 (TCCR0A) stejny pro vse krome nuly rjmp KEYRET KEY2: sbic PINC, 3 rjmp KEY3 ldi R16, 2 ldi R17, 0b00100011 rjmp KEYRET KEY3: sbic PINC, 4 rjmp KEY4 ldi R16, 3 ldi R17, 0b00100011 rjmp KEYRET KEY4: sbi PORTD, 0 cbi PORTD, 1 ;log. 0 to the row with 4, 5, 6, B sbi PORTD, 2 sbi PORTD, 3 sbic PINC, 2 rjmp KEY5 ldi R16, 4 ;pressed key 4 ldi R17, 0b00100011 rjmp KEYRET KEY5: sbic PINC, 3 rjmp KEY6 ldi R16, 5 ldi R17, 0b00100011 rjmp KEYRET KEY6: sbic PINC, 4 rjmp KEY7 ldi R16, 6 ldi R17, 0b00100011 rjmp KEYRET KEY7: sbi PORTD, 0 sbi PORTD, 1 cbi PORTD, 2 ;log. 0 to the row with 7, 8, 9, C sbi PORTD, 3 sbic PINC, 2 rjmp KEY8 ldi R16, 7 ;pressed key 7 ldi R17, 0b00100011 rjmp KEYRET KEY8: sbic PINC, 3 rjmp KEY9 ldi R16, 8 ldi R17, 0b00100011 rjmp KEYRET KEY9: sbic PINC, 4 rjmp KEYRET ldi R16, 9 ldi R17, 0b00100011 KEYRET: cbi PORTD, 0 ; log. 0 on all rows for next key press catch cbi PORTD, 1 cbi PORTD, 2 cbi PORTD, 3 out TCCR0A, R17 ret
[editovat] Cvičení 8 - Registr + Sedmisegmentovka
ATmega88 - Posuvný registr a sedmisegmentovka se změnou čísla při stisku jedničky na klávesnici.
.INCLUDE "m88def.inc" .ORG 0x0000 rjmp Main ; Reset Handler .ORG 0x0004 rjmp interrupt ; ovladani preruseni Main: ;inicializace portu pro rizeni ldi R16, 0b00001111 ; nastaveni vystupu out DDRD, R16 sbi PORTD, 3 sbi DDRC, 5 ;vstup pro klavesnici, klavesu 1 sbi PORTC, 5 ldi r16,0b00000001 ; Idle mode out SMCR,r16 ; Sleep mode set ldi r26, PCICR ; load address of PCICR in Y low clr r27 ; load high byte with 0 ldi r16,0b0000010 ; activate PCINT1 st X, r16 ; store new PCINT1 ldi r26, PCMSK1 ; load address of PCMSK1 in Y low clr r27 ; load high byte with 0 ldi r16,0b00100000 ; allow pin change interrupt on portC bit 5 st X, r16 ; store new PCMSK1 sei ; Enable interrupts spi: sleep nop rjmp spi interrupt: ; sbic PORTC, 5 ; rjmp interrupt sbic PORTC, 4 rjmp znak1 sbis PORTC, 4 rjmp znak2 reti znak1: cbi PORTD, 0 ;0 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 0 ;1 sbi PORTD, 2 cbi PORTD, 2 cbi PORTD, 0 ;0 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 2 ;0 cbi PORTD, 2 sbi PORTD, 0 ;1 sbi PORTD, 2 cbi PORTD, 2 cbi PORTD, 0 ;0 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 2 ;0 cbi PORTD, 2 sbi PORTD, 2 ;0 cbi PORTD, 2 cbi PORTC, 4 ret znak2: sbi PORTD, 0 ;1 sbi PORTD, 2 cbi PORTD, 2 cbi PORTD, 0 ;0 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 0 ;1 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 2 ;1 cbi PORTD, 2 sbi PORTD, 2 ;1 cbi PORTD, 2 sbi PORTD, 2 ;1 cbi PORTD, 2 cbi PORTD, 0 ;0 sbi PORTD, 2 cbi PORTD, 2 sbi PORTD, 2 ;0 cbi PORTD, 2 sbi PORTC, 4 ret
[editovat] Domácí cvičení 1 - PWM
.INCLUDE "m88def.inc" .EQU PWM_PULSES = 36 .EQU PWM_PULSES2 = 255 .ORG 0x0000 rjmp Main ; Reset Handler .ORG 0x0008 rjmp isr1 ; PCINT1 Handler 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 ;;;;;;;;;;; Klavesnice ;;;;;;;;;;; cbi DDRC, 2 ; set inputs for keyboard (COL1-3) sbi PORTC, 2 ; set internal Pull-Ups for keyboard ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PWM_INIT: ldi R17, 0b00100011 ; Fast PWM Mode, out on OC0B, non Inverting out TCCR0A, R17 sts TCCR2A, R17 ldi R17, 0b00001001 ; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1) out TCCR0B, R17 sts TCCR2B, R17 ldi R17, PWM_PULSES ; load number of clock pulses for 1 PWM period out OCR0A, R17 ldi R17, PWM_PULSES2; load number of clock pulses for 1 PWM period sts OCR2A, R17 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 r26, PCMSK1 ; load address of PCMSK1 in Y low clr r27 ; load high byte with 0 ldi r16,0b00000100 ; allow pin change interrupt on portC bits 2,3,4 st X, r16 ; store new PCMSK1 ;;;;;;;;;;; Vystupy ;;;;;;;;;;; sbi DDRD, 5 ; PWM 1 - PD5 sbi DDRD, 3 ; PWM 2 - PD3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADC_init: ldi r16,0b10000011 ; Enable ADC system clk/8 sts ADCSRA,r16 ldi r16,0b01100000 ; Input PC0 selected and Vcc as reference and data left alignment sts ADMUX,r16 ldi r16,0b00000000 ; Free running mode sts ADCSRB,r16 ldi r16,0b00000001 ; Digital input ADC0 disable sts DIDR0,r16 sei loop: rjmp ADC_start lds r16,ADCSRA ; nacteni konfigurace z ADC sbrs r16,(ADIF) ; kontrola hotoveho prevodu rjmp loop lds r16,ADCH sts OCR2B, r16 ; nastaveni hodnoty pro druhou PWM rjmp loop ADC_start: lds r16,ADCSRA ori r16,0b01000000 ; Start conversion sts ADCSRA,r16 ret isr1: rcall klavesa ldi r24, 0x2F ; nastaveni pocatecni hodnoty loop2: subi r24, 0x01 ; zmenseni o 1 out OCR0B, r24 rjmp WAIT cpi r24,0 brne loop2 reti ; return from Interrupt klavesa: ldi r16,36 out OCR0B, R16 ; nastaveni hodnoty do citace sbic PINC, 2 ; testovani zmackleho tlacitka ret rjmp klavesa WAIT: ldi R16, 4 WAIT1: inc R1 brne WAIT1 inc R2 brne WAIT1 dec R16 brne WAIT1 ret
[editovat] Semestrální práce
viz: Jiří Korbel, Ondřej Kovář, Tomáš Krč: Elektronický vrátný