Uživatel:Blahujos

Z MAM wiki

Verze z 15. 5. 2013, 20:17; Blahujos (diskuse | příspěvky)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Přejít na: navigace, hledání

Obsah

[editovat] Semestrální práce


Výstražný LED blikač

FUNKCE: blikání LEDkami v různých režimech a rychlostech

Režimy blikání:

  • jednoduché blikání
  • stroboskopické blikání
  • 2x rychle za sebou s následnou delší pauzou
  • běžící světlo zprava doleva a zpět
  • had

  • Ovládání pomocí dvou tlačítek (PD2 a PD3), jedno pro změnu režimu blikání a druhé pro změnu rychlosti blikání.
  • Režimy blikání jsou definované jako samostatné funkce.
  • Hlavní smyčka detekuje režim blikání a danou rychlost.
  • Vybraná funkce následné provede jeden krok a skončí. Čekání mezi kroky zajišťuje hlavní smyčka.
  • Součastně se pomocí časovače 0 (TCCR0) provádí testování tlačítek s následným nastavováním režimu a rychlosti

VYPNUTÍ:

  • 5 možných režimů snížené spotřeby (liší se spotřebou a možností probuzení procesoru z jednotlivých režimů)
  • režim zvolíme pomocí bitů SM2:0 v registru MCUCR (010 pro power-down)
  • uspání se musí povolit nastavením bitu SE (sleep enable) do log.1,
  • vhodný je režim Power-down, který má spotřebu ICC<1μA, kdy procesor

můžeme probudit vnějším přerušením INT0 nebo INT1

#define F_CPU 1000000UL   //zakladni frekvence 1 MHz
#include <avr/io.h>		
#include <util/delay.h>	
#include <avr/interrupt.h> 

#define RYCHLOST_MIN   	3	//min pocet bliknuti/s
#define RYCHLOST_MAX   	80 	//max pocet bliknuti/s
#define POCET_REZIMU 	15	//pocet rezimu
#define BLIKANI 0b00010111	//definice LED, ktere se stridaji pri zakladnim blikani
#define STROBO_CAS 	10		//cas(ms) sviceni LED pri rezimu STROBOSKOP a LETADLO
#define LETADLO 	80			//cas(ms) mezi bliknutim v rezimu LETADLO

//definice globalnich promennych
unsigned char rychlost; //rychlost blikani
unsigned char rezim;	//rezim blikani
unsigned char zmena;	//ukladani informace o zmene rezimu blikani
						//nastaveni zakladnich hodnot pri prvnim spusteni do funkci 

//definice funkci

/*****************************/
/*      Vektor přerušení     */
/*****************************/
ISR(TIMER0_OVF_vect)
	{
	static unsigned char tlacitko;	//staticka proměnna
									//informace, že minule bylo stisknuto tlacitko

	TCNT0=157;	//casovac zacne pocitat od 157 (255-157=98) preddelicka je 1024
				//tlacitka se kontroluji asi 10x/s (1 000 000 / 1024 / 98 = 10 Hz)
	if (tlacitko)	//minule stisknuto tlačítko
		{
		tlacitko=0;	//tlacitko vynulujeme
		return;		//ukonceni cyklu
		}			
	
	if (!(PIND&0b00000100)) 	//stisknute tlacitko 1, volba rezimu
		{
		rezim++;	//zmena rezimu
		zmena=1;	
		tlacitko=1;	//ulozeni informace o stisknuti
		}
		
	if (!(PIND&0b00001000))	//stisknute tlacitko 2, volba rychlosti
		{
		rychlost<<1;	//2x zrychleni
		tlacitko=1;		//ulozeni informace o stisknuti
		}

	if (rezim>POCET_REZIMU) //prekroceni poctu rezimu
		{
		rezim=1;			//opet se zacne od rezimu 1
		}

	if (rychlost>RYCHLOST_MAX)	//prekroceni max rychlosti
		{
		rychlost=RYCHLOST_MIN; //nastaveni rychlosti na min
		}
	
	
	} //konec vektoru preruseni, vrati se zpet

/*****************************/
/*    jednoduche blikani     */
/*****************************/
void blik (void)	
	{
	if (zmena)  //funkce spustena prvne
		{
		PORTB= BLIKANI;	//nastaveni do portu B pocatecni hodnotu 
		zmena=0;		//vynulovani promene zmena
		}
	else
		{
		PORTB=~PORTB; //v portu B bitova negace
		}
	}

/*****************************/
/*      stroboskop		     */
/*****************************/
void stroboskop (void)
	{
	PORTB=0xff;				//vsechny ledky rozsviti
	_delay_ms(STROBO_CAS);	//zpozdeni
	PORTB=0;				//zhasnuti
	}

/*****************************/
/*          letadlo          */
/*****************************/ 
void letadlo (void)
	{
	for(char n=0;n<2;n++) 		//cyklus o 2 opakovanich
		{
		PORTB=0xff;				//vsechny ledky rozsviti
		_delay_ms(STROBO_CAS);	//zpozdeni
		PORTB=0;				//zhasnuti
		_delay_ms(LETADLO);		//zpozdeni delsi
		}

	}

/*****************************/
/*       bezici svetlo       */
/*****************************/ 
void bezsvetlo (void)
	{
	static unsigned char pozice;	//staticka proměnna, uchovává hodnotu mezi volanimi fce=ukazatel, kde je zrovna LED							 
	if (zmena) //fce volana poprve
		{
		PORTB=1;	//zhasne vsechny LED a rozsviti jednu (PB0)
		pozice=1; 	//nastavi pozici na zacatek, 1.LED
		zmena=0;	
		return;     //ukonceni fce, 1.LED sviti, priste se posune
		}
	if (pozice<8)	//pozice jeste neni 8, nedoslo k 8me LED
		{
		PORTB<<=1;	//posun LED o 1 doleva.
		}
	else			//pozice je vetsi nebo rovna 8, LED dojela ke kraji 
		{
		PORTB>>=1;	//posun LED o 1 doprava
		}
	
	pozice++; 		//posun LED, proto se musi posunout ukazatel
	if(pozice>=15)	//ledka na 15. pozici, opet na zacatku
		{
		pozice=1;	//ukazatel na 1, zacatek
		}
	}


/*****************************/
/*            had            */
/*****************************/ 
void had (unsigned char delka)	
	{				
	
	static unsigned char pozice;	//ukazatel na pozici hada
									

	if (zmena) //fce volana prvne
		{
		PORTB=0;	//zhasnuti
		pozice=0; 	//pozice na zacatek, 1.LED
		zmena=0;	
		}
	
	if (pozice<delka)	//rozsvitilo se mene LED nez delka hada
		{
		PORTB <<=1;		//pridani clanku hada, bity se posunou doleva a vpravo se doplni 0
		
		PORTB ++;		//pricteni 1, nastaveni nulteho bitu na 1
		}			
	else				//pocet opakovani neni mensi nez delka hada, had je uplny
		{				
		
		PORTB <<=1;		//posuneme bity hada doleva a doplni se nula
		}
	
	pozice++; 			//posunuti LED, a tim i posun ukazatele
	
	if(pozice>(delka+8))//had je na konci, posledni clanek zmizi
		{
		pozice=0;		//ukazatel na 0, zacatek
		}
	
	}

/************************************************/
/*****************************/
/*       hlavní fce          */
/*****************************/ 

int main (void)
{
DDRB = 0xff;	//port B jako vystupni
TIMSK|=1; 		//nulty bit na 1 a ostatni se nechaji, povoleni preruseni od casovace 0
TCCR0 = 5;		//aktivace casovace 0 s preddelickou 1024

SREG  |= (1<<7);//povoleni preruseni, nastaveni 7. bitu registru SREG

rezim=1;		//nastaveni rezimu na 1.moznost
zmena=1;		//nastaveni zmena, zmena rezimu 

rychlost=RYCHLOST_MIN; //rychlost na min


/*       hlavni smycka       */


for(;;) 
	{	//smycka zajistuje vyber fce
	
	//vyber fce pomoci prikazu switch switch (vicenasobny if)
	
	switch (rezim) 	//rozhodnuti podle promenne rezim
		{
		case 1: 	//cislo 1
			blik(); //zavolani fce blik()
		break;		//vyskoceni z prikazu switch
		
		case 2:			//cislo 2
			strobo();	//zavolani fce strobo()
		break;
		
		
		case 3:			//cislo 3
			letadlo();	//zavolani fce letadlo()
		break;
		
		
		case 4:			//cislo 3
			semtam();	//zavolani fce bezsvetlo()
		break;
		
		
		default: 	//nebyl volen zadny z predchozich fci, zavola se tedy fce had
					
			had(rezim-4); 	//zavolani fce had, predani parametru (rezim - 4), ten pouzije fce k nastavení delky hada
		}
						
	//provedena volba fce, cekani nez se program pusti do dalsiho kroku	
	_delay_ms (1000/rychlost);	//cekani
	
	}

}

[editovat] Regulace otáček ventilátoru

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Regulace otacek ventilatoru PWM modulem s Timer0                  
;a pripojenou maticovou klavesnici na ATMega88.                    
;-------------------------------------------------------------  
;Regulace je mozna stiskem klaves 1-9 s postupnou zmenou     
;otacek. Stiskem 0 dojde k odpojeni ventilatoru.                 
;-------------------------------------------------------------
;Radky maticove klavesnice jsou pripojeny na PORTD0-3,             
;sloupce jsou pripojeny na PORTB0-3.                              
;Modul PWM(A) vyveden na PORTD6.                                  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


.include "m88def.inc"

.org $0000
	rjmp reset

.org $000E
	rjmp timer0_compareA

.org $000F
	rjmp timer0_compareB

.org $0010
	rjmp timer0_ovf


; preteceni TIMER0, nepouzite
timer0_ovf:
	reti

; pripravene obsluhy preruseni pro obe jednotky PWM, nepouzite
timer0_compareA:
	reti

timer0_compareB:
	reti




reset:


; nastaveni timer0 na Fast PWM
	ldi r20, 0b11110011
	out TCCR0A, r20

	ldi r20, 0x01
	out TCCR0B, r20

; nastaveni OCR0A + 0x20
	ldi r20, 200
	sts 0x47, r20

; nastaveni OCR0B + 0x20
	ldi r20, 20
	sts 0x48, r20

	ldi r20, 0x07
	sts TIMSK0, r20

; nastaveni vystupu PWM
	sbi DDRD, 5 ;jednotka A
	;sbi DDRD, 6 ;jednotka B

; sloupce maticove klavesnice, jako vstup s pull-up resistory
	cbi DDRB, 0
	cbi DDRB, 1
	cbi DDRB, 2
	cbi DDRB, 3

	sbi PORTB, 0
	sbi PORTB, 1
	sbi PORTB, 2	
	sbi PORTB, 3


; radky maticove klavesnice na PD0-3, vystupem ve vysoke impedanci s PORTD v 0
	cbi DDRD, 0
	cbi DDRD, 1
	cbi DDRD, 2
	cbi DDRD, 3
	
	cbi PORTD, 0
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3


; povoleni preruseni
	;sei

smycka:

;radka 1

	sbi DDRD, 0 ; prvni radka jako vystup v log. 0
	
	sbis PINB, 0
	rcall rychlost1

	sbis PINB, 1
	rcall rychlost2

	sbis PINB, 2
	rcall rychlost3

	cbi DDRD, 0 ; prvni radka zpet do vysoke impedance

; radka 2

	sbi DDRD, 1 ; druha radka do log. 0

	sbis PINB, 0
	rcall rychlost4

	sbis PINB, 1
	rcall rychlost5

	sbis PINB, 2
	rcall rychlost6

	cbi DDRD, 1 ; druha radka do vysoke impedance

; radka 3

	sbi DDRD, 2 ; treti radka do log. 0

	sbis PINB, 0
	rcall rychlost7

	sbis PINB, 1
	rcall rychlost8

	sbis PINB, 2
	rcall rychlost9

	cbi DDRD, 2 ; treti radka do vysoke impedance

; radka 4

	sbi DDRD, 3 ; ctvrta radka do log. 0

	sbis PINB, 1
	rcall rychlost0

	cbi DDRD, 3 ; ctvrta radka do vysoke impedance


	rjmp smycka


rychlost1:
	ldi r30, 0b11110011 ; znovu zapnuti PWM vystupu 
	out TCCR0A, r30
	ldi r20, 0 ; zmena komparacni urovne
	sts 0x47, r20
	ret

rychlost2:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 30
	sts 0x47, r20
	ret

rychlost3:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 60
	sts 0x47, r20
	ret

rychlost4:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 90
	sts 0x47, r20
	ret

rychlost5:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 120
	sts 0x47, r20
	ret

rychlost6:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 150
	sts 0x47, r20
	ret

rychlost7:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 180
	sts 0x47, r20
	ret

rychlost8:
	ldi r30, 0b11110011 
	out TCCR0A, r30
	ldi r20, 210
	sts 0x47, r20
	ret

rychlost9:
	ldi r30, 0b11110011
	out TCCR0A, r30
	ldi r20, 240
	sts 0x47, r20
	ret

; odpojeni PWM
rychlost0:
	ldi r30, 0b00110011 ; odpojeni PWM modulu
	out TCCR0A, r30
	cbi PORTD, 6 ; log. 0 na vystup
	ret

[editovat] Posuvný registr jako výstupní periferie, připojení sedmisegmentového displeje se spol. anodou přes 74HCT595

.include "m88def.inc"

.equ PORT_REGISTR = PORTB
.equ DDR_REGISTR = DDRB

.equ OE    = 0 ; output enable (active LOW)
.equ DS    = 1 ; serial data input
.equ SH_CP = 2 ; shift register clock input
.equ ST_CP = 3 ; storage register clock input
.equ MR    = 4 ; master reset (active LOW)

.org $0000
	rjmp reset

zapis_do_registru:

	;sbi PORT_REGISTR, OE ; vystup ve vysoke impedanci
	sbi PORT_REGISTR, MR ; neni reset
	cbi PORT_REGISTR, SH_CP ; hodiny na nulu
	cbi PORT_REGISTR, ST_CP ; hodiny na nulu

	ldi r21, 0x08 ; promenna na cykleni

	cyklus:

	cbi PORT_REGISTR, SH_CP ; hodiny na 0
	rcall cekej
	
	sbrs r20, 7
	sbi PORT_REGISTR, DS ; DS na 1
	sbrc r20, 7
	cbi PORT_REGISTR, DS ; DS na 0

	lsl r20 ; posun vysilanych dat
	nop
	nop
	nop

	sbi PORT_REGISTR, SH_CP ; hodiny na 1
	rcall cekej

	dec r21
	breq konec
	rjmp cyklus

	konec:

	sbi PORT_REGISTR, ST_CP ; nabezna hrana k zapisu dat
	cbi PORT_REGISTR, OE ; povoleni vystupu

	rcall cekej

	ret

reset:

	sbi DDR_REGISTR, OE
	sbi DDR_REGISTR, DS
	sbi DDR_REGISTR, SH_CP
	sbi DDR_REGISTR, ST_CP
	sbi DDR_REGISTR, MR

	sbi PORT_REGISTR, OE ; vystup ve vysoke impedanci

	ldi r20, 0b00101010 ; data k zapisu, ktere zobrazi cislovku 3
	rcall zapis_do_registru ; zapis dat do registru

smycka:
	rjmp smycka

; kratke cekani
cekej:
	ldi r25, 20

	cekej_tu:

	dec r25
	breq fin
	rjmp cekej_tu

	fin:

	ret

[editovat] 1.domací úkol

Spolupráce s Miroslavem Strobem a Martinem Vitvarem.

.include "m88def.inc"

.org $0000
	rjmp reset

.org $0001
	rjmp ext_preruseni

.org $000D
	rjmp timer1_ovf

.org $000E
	rjmp timer0_compareA

.org $000F
	rjmp timer0_compareB

.org $0010
	rjmp timer0_ovf

.org $0015
	rjmp prevodnik


.equ milivterinovy_citac = 0x0100

ext_preruseni:

	push r22

	lds r22, 0x69 ; EICRA - nastaveni ext preruseni
	cpi r22, 0x00 ; reaguje na log. 0
	breq nula

	; dalsi preruseni bude pri log. 0
	ldi r22, 0x00
	sts 0x69, r22 ;EICRA

	; spusteni TIMER1
	;;;;;
	ldi r22, 0x04
	sts 0x81, r22 ;TCCR1B

	clr r22
	out TIFR1, r22

	; preruseni odpovida cca 5 s
	ldi r22, 0xB3 ;TCNT1H
	sts 0x85, r22

	ldi r22, 0xB4 ;TCNT1L
	sts 0x84, r22

	ldi r22, 0x01
	sts 0x6F, r22 ;TIMSK1
	;;;;;

	clr r22
	sts 0x47, r22 ; znulovat OCR0A

	rcall odpojit_pwmA
	sbi PORTD, 5

	rjmp konec

	nula:
	; dalsi preruseni se nastavi na nabeznou hranu
	ldi r22, 0x03
	sts 0x69, r22 ;EICRA
	sbi PORTD, 5 ;rozsvitime svetlo

	rcall zakaz_timer1
	
	konec:

	pop r22

	reti

timer1_ovf:

	push r22
	push r23


	ldi r22, 0xFF ;TCNT1H
	sts 0x85, r22

	ldi r22, 225 ;TCNT1L
	sts 0x84, r22

	; zmena nastaveni PWM
	lds r23, 0x47 ; OCR0A	

	cpi r23, 0x00 ; prvotni prubeh - musi se povolit PWM modul
	brne rien1
	rcall pripojit_pwmA

	rien1:

	cpi r23, 0xFF ; posledni prubeh - musi se zakazat PWM modul
	brne rien2
	rcall zakaz_timer1
	rcall odpojit_pwmA

	rien2:

	inc r23 ; na samem konci po 0xFF opet nastavi vychozi stav 0x00
	sts 0x47, r23

	pop r23
	pop r22
	
	reti

; preteceni TIMER0, po cca 1ms 
timer0_ovf:

	push r22
	push r23
	push r24
	push r25

	ldi r23, 134
	out TCNT0, r23

	lds r25, milivterinovy_citac

	; spusti AD prevod kazdych cca 100ms

	cpi  r25, 100 

	brne preskoc_prevod
	
	rcall spustit_adc_prevod
	clr r25
		
	preskoc_prevod:

	inc r25 ; inkrementuje milivterinovy citac
	sts milivterinovy_citac, r25

	pop r25
	pop r24
	pop r23
	pop r22

	reti

; pripravene obsluhy preruseni pro obe jednotky PWM, nepouzite
timer0_compareA:
	reti

timer0_compareB:
	reti

; obsluha ADC predvodu
prevodnik:

	push r22

	ldi r22, 0x79 ; precte ADCH
	; nastaveni OCR0B
	sts 0x48, r22

	pop r22

	reti

reset:


	; vynulovani milivterinoveho citace
	clr r0 ; pomocny vzdy nulovy registr
	sts milivterinovy_citac, r0

; nastaveni timer0 na Fast PWM
	ldi r20, 0b11110011
	out TCCR0A, r20

	ldi r20, 0x02
	out TCCR0B, r20

; nastaveni OCR0A + 0x20
	ldi r20, 200
	sts 0x47, r20

; nastaveni OCR0B + 0x20
	ldi r20, 20
	sts 0x48, r20

	ldi r20, 0x07
	sts TIMSK0, r20

; nastaveni vystupu PWM
	sbi DDRD, 5 ;jednotka A
	sbi DDRD, 6 ;jednotka B


; nastaveni externiho preruseni
	clr r20
	sts 0x69, r20 ; EICRA, reaguje na log. 0
	ldi r20, 0x01
	sts 0x3D, r20

; nastaveni prevodniku
	ldi r20, 0x20
	sts 0x7C, r20 ; nastaveni ADMUX

	ldi r20, 0b10001000
	sts 0x7A, r20

; odpojeni PWM modulu A
	rcall odpojit_pwmA

; povoleni preruseni
	sei

smycka:
	rjmp smycka

spustit_adc_prevod:

	lds r24, 0x7A
	ldi r25, 0b01000000
	or r24, r25	
	sts 0x7A, r24

	ret

pripojit_pwmA:
	
	in r20, TCCR0A
	ori r20, 0b11000000
	out TCCR0A, r20

	ret

odpojit_pwmA:

	in r20, TCCR0A
	andi r20, 0b00111111
	out TCCR0A, r20

	cbi PORTD, 5

	ret

zakaz_timer1:

	clr r22
	sts 0x6F, r22 ;TIMSK1
	sts 0x36, r22 ;TIFR1
	ret
Osobní nástroje