Uživatel:Trisktom
Z MAM wiki
Řádka 1 019: | Řádka 1 019: | ||
unsigned char casovac; | unsigned char casovac; | ||
unsigned char doba; | unsigned char doba; | ||
+ | unsigned char poceturychleni; | ||
int main() { | int main() { | ||
Řádka 1 027: | Řádka 1 028: | ||
ADCSRB=0b000; | ADCSRB=0b000; | ||
- | while(1){ | + | while(1){ |
- | if( | + | if(poceturychleni<10){ |
- | _delay_ms(5); | + | _delay_ms(5); |
- | continue; | + | continue; |
+ | } | ||
+ | if(predeslahodnota<ADCL){ | ||
+ | vzestup=1; | ||
+ | predeslahodnota=ADCL; | ||
+ | } | ||
+ | if(predeslahodnota==ADCL){ | ||
+ | vzestup=1; | ||
+ | predeslahodnota=ADCL; | ||
+ | } | ||
+ | if(predeslahodnota>ADCL){ | ||
+ | vzestup=1; | ||
+ | predeslahodnota=ADCL; | ||
+ | } | ||
+ | if ((pokles==1)&&(pomocna==1)){ | ||
+ | pokles=0; | ||
+ | vzestup=0; | ||
+ | pomocna=0; | ||
+ | kmit(); | ||
+ | } | ||
+ | } | ||
+ | |||
} | } | ||
- | + | ||
- | + | void kmit(){ | |
- | + | if (casovac==0){ | |
- | + | TCCR0A=0b10; | |
- | if( | + | TCCR0B=0b100; |
- | + | TIMSK0=0b10; | |
- | + | casovac=1; | |
- | + | } else { | |
- | + | TCCR0B=0; | |
- | + | doba=TCNT0; | |
- | + | casovac=0; | |
- | } | + | OCR0A=doba; |
- | + | urychleni(); | |
- | + | } | |
- | + | ||
- | + | ||
- | + | ||
} | } | ||
+ | void urychleni(){ | ||
+ | PORTD|= (1<<PD0); | ||
+ | _delay_ms(1); | ||
+ | PORTD&= ~(1<<PD0); | ||
+ | OCR0A=OCR0A-1; | ||
} | } | ||
+ | ISR(TIMER0_COMP_vect){ | ||
+ | urychleni(); | ||
+ | TCNT0=0; | ||
+ | poceturychleni++; | ||
} | } | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
</pre> | </pre> | ||
Čerpáno od kolegy z minulého roku.([http://noel.feld.cvut.cz/vyu/a2m99mam/index.php/U%C5%BEivatel:Kacermar Kacerma]) | Čerpáno od kolegy z minulého roku.([http://noel.feld.cvut.cz/vyu/a2m99mam/index.php/U%C5%BEivatel:Kacermar Kacerma]) |
Aktuální verze z 16. 5. 2013, 07:02
Blikání LEDky + klávesnice
; ; 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 DDRD = $17 ; DDRB address .EQU PORTD = $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 ; 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, 0 SBI PORTB, 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 led:SBIS PINB,LED_X SBI PORTB,LED_X CBI PORTB,LED_X RET ; 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 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 reti ; return from Interrupt ; 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 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 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 PORTD, 0 ; log. 0 on all rows for next key press catch cbi PORTD, 1 cbi PORTD, 2 cbi PORTD, 3 ret
PWM ventilátor s klávesnicí ze cvičení
;; ; 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 ; ; To do: *** Catch only the key press, not key release ; ; To do: *** 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 "m188def.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 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 reti ; return from Interrupt ; 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 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 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 PORTD, 0 ; log. 0 on all rows for next key press catch cbi PORTD, 1 cbi PORTD, 2 cbi PORTD, 3 ret
Ventilátor s klávesnicí 2
.include "m88def.inc" .org 0x0000 rjmp start .org 0x0004 rjmp klavesa start: cbi DDRC,0 cbi DDRC,1 cbi DDRC,2 cbi DDRC,3 sbi PORTC,0 sbi PORTC,1 sbi PORTC,2 sbi PORTC,3 sbi DDRD,0 sbi DDRD,1 sbi DDRD,2 sbi DDRD,3 cbi PORTD,0 cbi PORTD,1 cbi PORTD,2 cbi PORTD,3 ldi R26,PCICR clr R27 ldi R16,0b00000011 st X, R16 ldi r26,PCMSK1 clr r27 ldi r16,0b00001111 st X, r16 sei ldi R16,0b00110011 out TCCR0A,R16 ldi R16,0b00000001 out TCCR0B,R16 ldi R16,0x7F out OCR0B,R16 sbi DDRD,5 smycka: nop out OCR0B,R16 rjmp smycka klavesa: in R17,OCR0B key0: ;sbi PORTD,0 ;sbi PORTD,1 ;sbi PORTD,2 ;cbi PORTD,3 cbi DDRD,0 cbi DDRD,1 cbi DDRD,2 sbi DDRD,3 cbi PORTD,3 sbic PINC,1 rjmp key1 ldi R16,0 rjmp keyret key1: ;cbi PORTD,0 ;sbi PORTD,1 ;sbi PORTD,2 ;sbi PORTD,3 cbi DDRD,1 cbi DDRD,2 cbi DDRD,3 sbi DDRD,0 cbi PORTD,0 sbic PINC,0 rjmp key2 ldi R16,28 rjmp keyret key2: sbic PINC,1 rjmp key3 ldi R16,59 rjmp keyret key3: sbic PINC,3 rjmp key4 ldi R16,87 rjmp keyret key4: ;sbi PORTD,0 ;cbi PORTD,1 ;sbi PORTD,2 ;sbi PORTD,3 cbi DDRD,0 cbi DDRD,2 cbi DDRD,3 sbi DDRD,1 cbi PORTD,1 sbic PINC,0 rjmp key5 ldi R16,115 rjmp keyret key5: sbic PINC,1 rjmp key6 ldi R16,143 rjmp keyret key6: sbic PINC,2 rjmp key7 ldi R16,171 rjmp keyret key7: ;sbi PORTD,0 ;sbi PORTD,1 ;cbi PORTD,2 ;sbi PORTD,3 cbi DDRD,0 cbi DDRD,1 cbi DDRD,3 sbi DDRD,2 cbi PORTD,2 sbic PINC,0 rjmp key8 ldi R16,199 rjmp keyret key8: sbic PINC,1 rjmp key9 ldi R16,227 rjmp keyret key9: sbic PINC,2 rjmp keyret ldi R16,255 rjmp keyret keyret: sbi DDRD,0 sbi DDRD,1 sbi DDRD,2 sbi DDRD,3 cbi PORTD,0 cbi PORTD,1 cbi PORTD,2 cbi PORTD,3 out OCR0B,R16 ;pop r16 reti
Sedmisegmentovka
;-----------INICIALIZACE---------- .INCLUDE "m88def.inc" .EQU RES = 0 .EQU OUT_ENABLE = 1 .EQU INPUT = 2 .EQU SHIFT_CLK = 3 .EQU STORE_CLK = 4 .ORG 0x000 rjmp main ; .ORG 0x003 rjmp stisk ; přerušení vyvolané klávesnicí main: ldi r16,high(RAMEND) ;nastavení zásobníku?? out SPH,r16 ldi r16,low(RAMEND) out SPL,r16 ;aktivace sleep modu ldi r16,0b00000001 out SMCR,r16 clr r16 ;vynulvání používaných registrů - pro jistotu ldi r17,0b00001000 ;osmicka pro dekrementaci při sériovém plnění posuvného reg. clr r18 ;pro porovnávání předchozího registru ;---------NASTAVENÍ PŘERUŠENÍ-------------- ;nastavim přerušení PCINT0, piny PCINT0-7, vektor 003 ldi r26, PCICR clr r27 ldi r16,0b00000001 st X, r16 ;aktivuju pin PB1 jako aktivní pro přerušení klávasnicí ldi r26, PCMSK0 clr r27 ldi r16,0b00000010 st X, r16 sei ; na pinu B1 čtení, na pinu B0 buzení nulou cbi DDRB,1 sbi PORTB,1 sbi DDRB,0 cbi PORTB,0 ;---------NASTAVENÍ KOMUNIKACE S SHIFT REGISTREM--------------- ; nastavení bitů komunikujících s registrem sbi DDRC,0 sbi DDRC,1 sbi DDRC,2 sbi DDRC,3 sbi DDRC,4 CBI PORTC,RES SBI PORTC,RES CBI PORTC,OUT_ENABLE CBI PORTC,INPUT CBI PORTC,SHIFT_CLK CBI PORTC,STORE_CLK ;---------STAV DISPLEJE PO RESETU---------------- ldi r16,0b11000000 ;nula na sedmisegmentovce (spol. anoda = inverzní) rcall zapis_znak ;----------- ...TADY JÁ BUDU SKORO FURT... --------------- spat: sleep nop rjmp spat ;-------------PROCEDURY--------------- ;prohození nuly a jedničky na 7segmentovce v registru r16 urci_znak: ldi r19,0b11000000 cpse r16,r19 rjmp zmen_znak1 rjmp zmen_znak2 zmen_znak2: ldi r16,0b11111001 ret zmen_znak1: ldi r16,0b11000000 ret ; zapsání znaku 7segmentovky do posuvného registru a zobrazení zapis_znak: cbi PORTC,OUT_ENABLE ror r16 brcs jedna ;podprogram pro zápis 1 do shift brcc nula ;podprogram pro zápis 0 do shift zpet: dec r17 ;Dekrementuje registr kde je 9 cpse r17,r18 ;až proběhne 8krát, bude R17 = 0 (=r18) a přestane se opakovat zápis rjmp zapis_znak sbi PORTC,STORE_CLK cbi PORTC,STORE_CLK sbi PORTC,OUT_ENABLE ror r16 ldi r17,0b00001000 ret jedna: SBI PORTC,INPUT SBI PORTC,SHIFT_CLK CBI PORTC,SHIFT_CLK rjmp zpet nula: CBI PORTC,INPUT SBI PORTC,SHIFT_CLK CBI PORTC,SHIFT_CLK rjmp zpet ;----------------OBSLUHA PŘERUŠENÍ----------- stisk: rcall urci_znak rcall zapis_znak reti
1. domácí úkol
.NOLIST .INCLUDE "m88def.INC" .LIST ;PORTC .EQU Button = 0 ; na PC0 tlacitko, spina pull-up rezistor na zem. .EQU Trimmer = 1 ; vstup z trimru, komparator ADC1 ;PORTD .EQU Light = 0 ; port PD0 ovlada osvetleni interieru .EQU Board = 1 ; port PD1 ovlada osvetleni palubovky ;NADEFINOVANI REGISTRU .DEF Temp = r16 ; docasny registr pro prenos hodnot .DEF PWM_In = r17 ; hodnota PWM pro osvetleni interieru .DEF PWM_Board = r18 ; hodnota PWM pro palubni desku .DEF Symptoms = r19 ; registr priznaku .DEF T5 = r20 ; citac pro 5s osvetleni interieru .DEF T2 = r21 ; citac pro postupne zhasinani behem 2s ;SYMPTOMS .EQU S_Timer1 = 0 ; bit0 registru Symptoms rika, zda doslo k preruseni od Timer1 .EQU S_In_ON = 1 ; bit1, zda sviti svetlo interieru .EQU S_Second = 2 ; bit2, zda probiha druhy cyklus citani registru T5 .EQU S_Twilight = 3 ; bit3, zda probiha 2s proces stmivani ;KONSTANTY PRO PWM .EQU PWM_In_Pulse = 40 ; PWMfreq 25 kHz pro osvetleni interieru .EQU PWM_Board_Pulse = 36 ; PWMfreq 27,8kHz pro osvetleni palubi desky ;RESET A INTERUPTION VEKTORY .ORG 0x000 RJMP START ; reset vektor .ORG 0x00D RJMP Timer1_Over ; preruseni pri preteceni Timer1 ;PORTY LDI Temp, 0b11111100 ; PC0 je vstup ADC a PC0 je vstup pro Button OUT DDRC, Temp ; LDI Temp, 0b00000001 ; vystupy do 0 a interni pull-up pro PC0 OUT PORTC, Temp ; SER Temp ; PORTD a PORTB jako vystupy OUT DDRD, Temp ; OUT DDRB, Temp ; CLR Temp ; PORTD a PORTB nastavit do 0 OUT PORTD, Temp ; OUT PORTB, Temp ;---------------------------------------------------------------------------------------------------- START: ;inicializace zasobniku LDI Temp,high(RAMEND) OUT SPH, Temp LDI Temp,low(RAMEND) OUT SPL, Temp ;----PWM----PWM----PWM----PWM----PWM----PWM----PWM----PWM----PWM----PWM---- ;INTERIER LDI Temp, 0b00100011 ; Fast PWM Mode, OUT on OC0B, non Inverting OUT TCCR0A, Temp LDI Temp, 0b00001001 ; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1) OUT TCCR0B, Temp LDI Temp, PWM_In_Pulse ; load number of clock pulses for 1 PWM period OUT OCR0A, Temp IN Temp, TCCR0A ; odpojeni vystupu od PWM generatoru (standartni vystup v 0) CBR Temp, 0x10 OUT TCCR0A, Temp ; ;BOARD LDI Temp, 0b00100011 ; Fast PWM Mode, OUT on OC0B, non Inverting STS TCCR2A, Temp ; LDI Temp, 0b00001001 ; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1) STS TCCR2B, Temp ; LDI Temp, PWM_Board_Pulse ; load number of clock pulses for 1 PWM period STS OCR2A, Temp ; ;ADC LDI Temp, 0b11100000 ; Vniřtní reference 1,1V, kapacitor na AREF,zarovnání Left, ADC0 STS ADMUX, Temp ; LDI Temp, 0b10000100 ; ADC enabled, int. off, autotriger off, prescaler 16 (62,5kHz) STS ADCSRA, Temp ; CLR Temp ; deaktivace autotrigeru STS ADCSRB, Temp ; LDI Temp, 0x02 ; disable digital input buffer for pin ADC1 (snizeni spotreby) STS DIDR0, Temp ; ;PRERUSENI OD Timer1 LDI Temp, 0xD8 ; nastavi Timer1 na 10000 (10E+4 * 1us = 10ms) STS TCNT1H, Temp LDI Temp, 0xF0 STS TCNT1L, Temp ; CLR Temp ; CLR TCCR1A STS TCCR1A, Temp ; LDI Temp, 0b00000001 ; Clock Select -> CLKio/1 (no prescaler) STS TCCR1B, Temp ; STS TIMSK1, Temp ; povoleni preruseni pri preteceni Timer1 SEI ; povoleni preruseni CLR Temp ; vynulovani hodnoty T2 MOV T2, Temp ; ;-----MAIN PROGRAM------------------------------------------------------------------------------ Main: SBRS Symptoms, S_Timer1 ; bylo preruseni od Timer1? RJMP Main ; NE preskoc testovani tlacitka a ADC, hodnoty PWM se nemeni CLT ; ANO, zrus priznak preruseni od Timer1 BLD Symptoms, S_Timer1 ; RCALL Butt ; otestuj, zda je stisknute tlacitko SBRC Symptoms, S_In_ON ; sviti interier? RCALL Watcher ; ANO, dekrementuj hodnotu T5 nebo T2 OUT OCR0B, PWM_In ; nastav PWM interieroveho svetla podle aktualni hodnoty RCALL AD_Convert ; zjisti hodnotu napeti z potenciometru STS OCR2B, PWM_Board ; nastav PWM svetla palubni desky podle aktualni hodnoty RJMP Main ;-----SECONDARY FUNCTIONS--------------------------------------------------------------------------------------------- Timer1_Over: ; ulozeni Status registru do zasobniku PUSH Temp ; IN Temp, SREG ; PUSH Temp ; reinicializace Timer1 LDI Temp, 0xD8 ; nastav Timer1 na hodnotu 10000 (10E+4 * 1us = 10ms) STS TCNT1H, Temp LDI Temp, 0xF0 STS TCNT1L, Temp ; SET ; nastav priznak, ze doslo k preruseni od Timer1 BLD Symptoms, S_Timer1 ; POP Temp ; obnoveni Status registru ze zasobniku pro navrat z preruseni OUT SREG, Temp POP Temp ; RETI Butt: ; testovani tlacitka SBIC PINC, Button ; je tlacitko stisknute? RET ; NE, ukonci testovani tlacitka SET ; ANO, nastav priznak, ze interier sviti BLD Symptoms, S_In_ON ; LDI PWM_In, PWM_In_Pulse ; PWM na nejvetsi stridu IN Temp, TCCR0A ; pripojeni PWM generatoru na vystup SET BLD Temp, 5 OUT TCCR0A, Temp ; LDI Temp, 0xFF ; ulozi do T5 hodnotu 255 MOV T5, Temp ; CLT ; BLD Symptoms, S_Second ; vynuluj priznak Second - nedoslo k druhemu pricitani T2 BLD Symptoms, S_Twilight ; neprobiha proces stmivani RET Watcher: SBRC Symptoms, S_Twilight ; bezi proces Twilight? RJMP Twilight ; ANO, prejdi na Twilight DEC T5 ; NE, bezi 5s plneho svitu, dekrementuj T5 BRNE Return ; kdyz neni nula, konec SBRC Symptoms, S_Second ; kdyz je nula, bezel uz druhy cyklus? RJMP Twilight ; ANO, skoncilo 5s plneho svitu, zacni stmivat SET ; NE, nastav priznak, ze T5 jde znovu BLD Symptoms, S_Second ; RJMP Return ; Twilight: SET ; nastaveni priznaku, ze odted dochazi ke stmivani BLD Symptoms, S_Twilight ; INC T2 ; zvys hodnotu T2, hodnota 10 -> 100ms MOV Temp, T2 ; T2 nejde porovnat primo instrukci CPI (r1) CPI Temp, 0x0A ; testuj na 10 BRNE Return ; kdyz neni 10, nic se nedeje CLR Temp ; kdyz je 10, zacni znova MOV T2, Temp ; SUBI PWM_In, 0x02 ; odecti hodnotu 2 od aktualniho svitu (20 kru) TST PWM_In ; otestuj, zda doslo k nule? BRNE Return ; NE, vrat se zpet CLT ; ANO, stmivani dokonceno (interier je zhasnuty) BLD Symptoms, S_In_ON ; zrus priznak stmivani IN Temp, TCCR0A ; odpojeni vystupu od PWM generatoru (standartni vystup v 0) CLT BLD Temp, 5 ; CLR 5.bit OUT TCCR0A, Temp ; AD_Convert: CLR Temp ; odstran vysledek posledniho prevodu STS ADCH, Temp ; LDS Temp, ADCSRA ; prekopiruj ADCSRA do Temp SET ; nastav 6.bit, tj. zacatek AD prevodu BLD Temp, 6 ; STS ADCSRA, Temp ; spusteni AD prevodu AD_Run: LDS Temp, ADCSRA ; prekopiruj ADCSRA do Temp SBRC Temp, 6 ; je ADSC nastaven? RJMP AD_Run ; ANO, testuj znovu ; NE, prevod skoncil, vysledek ulozen do ADCH ; uprava vysledku pro pouziti v PWM LDS Temp, ADCH ; hodnotu H bytu z AD prevodu do Temp LSR Temp ; /2 LSR Temp ; /2 LSR Temp ; /2 MOV PWM_Board, Temp ; hodnota ADCH/8 do PWM_Board LDI Temp, 0x04 ; ADD PWM_Board, Temp ; pricte k PWM_Board 4 RET Return: RET
Obsah |
[editovat] SEMESTRÁLNÍ PRÁCE - KYVADLO
[editovat] Zadání:
Připojte k AVR cívku, která bude detekovat kyv magnetu zavěšeného nad ní a ve vhodných okamžicích magnet urychlovat. Zvažte možnost použít místo magnetu jen kousek železa.
[editovat] Schéma:
[editovat] Komentář k programu:
V návrhu využíváme A/D převodník ke sledování napětí na portu PC0(neboli ADC0). Hledáme maximum tohoto napětí. V okamžiku, kdy je nalezeno maximum je spuštěn časovač a v okamžiku, kdy je opět nalazeno maximum, je tento časovač vypnut. Výstupem je časový údaj charakterizující jeden kyvy(tzn. polovinu periody).
Pokud chceme magnet urychlovat je nutné, abychom ve vhodném okamžiku(pokles z maxima) poslali skrze port PD0 logickou 1, a tím indukovali magnetické pole v cívce. To způsobí urychlení kyvu magnetu.
Při použití kusu železa nelze detektovat kyv, protože železo samo o sobě neprodukuje magnetické pole. Lze ho však urychlovat stejně jako v minulém případě(PD0 do logické 1).
[editovat] Kód:
#include "avr/io.h" #include "avr/delay.h" #include "avr/interrupt.h" unsigned char predeslahodnota; unsigned char vzestup; unsigned char pokles; unsigned char pomocna; unsigned char casovac; unsigned char doba; unsigned char poceturychleni; int main() { DDRD |= (1<<PD0); PORTD&= ~(1<<PD0); ADMUX= 0b01000000; ADCSRA=0b11000001; ADCSRB=0b000; while(1){ if(poceturychleni<10){ _delay_ms(5); continue; } if(predeslahodnota<ADCL){ vzestup=1; predeslahodnota=ADCL; } if(predeslahodnota==ADCL){ vzestup=1; predeslahodnota=ADCL; } if(predeslahodnota>ADCL){ vzestup=1; predeslahodnota=ADCL; } if ((pokles==1)&&(pomocna==1)){ pokles=0; vzestup=0; pomocna=0; kmit(); } } } void kmit(){ if (casovac==0){ TCCR0A=0b10; TCCR0B=0b100; TIMSK0=0b10; casovac=1; } else { TCCR0B=0; doba=TCNT0; casovac=0; OCR0A=doba; urychleni(); } } void urychleni(){ PORTD|= (1<<PD0); _delay_ms(1); PORTD&= ~(1<<PD0); OCR0A=OCR0A-1; } ISR(TIMER0_COMP_vect){ urychleni(); TCNT0=0; poceturychleni++; }
Čerpáno od kolegy z minulého roku.(Kacerma)