Uživatel:Havraale

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Programátor a IDE

Jednoduchý programátor přes sériovou linku. Zde připojený k ATtiny2313. Software pro nahrání programu do procesoru: PonyProg - serial device programmer ([1])

Jednoduchý programátor přes USB: USBtinyISP Software pro nahrání programu do procesoru: AVRdude

Programovací prostředí: CodeVisionAVR ([2])


Seznam součástek:

C1       330n          
C2       100n
D1       BZX83V005.1
D2       BZX83V005.1
IC1      78L05
R1       15k
R2       10k
R3       4k7
R4       4k7
T1       BC547C
U$1      ATTINY2313
X1       konektor 9-pin F


Soubor:ATp.png


[editovat] Semestrální práce - Dálkové oládání s modulem RFM12B

[editovat] Zadání

Úkolem je postavit dálkové ovládání s modulem RFM12B a procesorem ATtiny2313V. Vysílač má mít 2 tlačítka, která budou ovládat 2 LED na přijímači.


[editovat] Modul RFM12B

RFM12B je rádiový modul pracující v ISM pásmu. Existují verze pro pásma 433 MHz, 868 MHz a 915 MHz.

Vlastnosti:

  • Přenosová rychlost 115,2 kb/s (interní demodulátor), nebo 256 kb/s externím RC filtrem
  • Napájecí napětí 2,2 V – 3,8 V
  • Odběr v úsporném režimu < 0,3 uA
  • Diferenciální anténní vstup/výstup
  • Automatické přizpůsobení k anténě
  • Rychlý fázový závěs s vysokým rozlišením – krok 2,5 kHz
  • SPI
  • Modulace FSK
  • Krystal 10 MHz
  • Rozměry 16 mm x 16 mm x 2,2 mm
Literatura
 Datasheet, programming guide RFM12B
 Návod Zde

[editovat] Zapojení

RFM12B        ATtiny2313V
SCK    <--    PB7
SDI    <--    PB6
SDO    -->    PB5
nSEL   <--    PB4
nIRQ   -->    PB3
FSK/DATA/nFFS přes odpor 10k na napájení +3 V

Modul a PCB pro testování 
Soubor:RFM12B.png

[editovat] SPI

Komunikace mezi modulem a procesorem je přes SPI. Procesor je master. Modul je připojen na PORTB. Výstupy jsou 7, 6, 4 a 0 pro LED na vysílači, ostatní jsou vstupy s vysokou impedancí.


//pin RFM12B      pin portu B na uP
#define SCK      7                    // SPI clock
#define SDI      6                    // SPI Data input  (RFM12B side) - Master output AVR DO
#define SDO      5                    // SPI Data output (RFM12B side)
#define nSEL     4                    // Chip select
#define nIRQ     3                    // Interrupt

PORTB=0x14;
DDRB=0xD1;


[editovat] Softwarové SPI

#define HI_B(x) PORTB |=  (1<<(x))
#define LO_B(x) PORTB &= ~(1<<(x))
unsigned int swSPI(unsigned int Cmd) {
  unsigned char i;
  unsigned int recv=0;
  LO_B(SCK);
  LO_B(nSEL);
  for(i=0; i<16; i++) {     
    if(Cmd&0x8000) HI_B(SDI); else LO_B(SDI);
    HI_B(SCK);
    recv<<=1; 				
    if( PINB&(1<<SDO) ) {
      recv|=0x0001;
    }
    LO_B(SCK);
    Cmd<<=1;   
  }
  HI_B(nSEL);
  return recv;
}


[editovat] Hardwarové SPI

Rychlá verze (asi 0,5 fclk ), používá USI.

unsigned int hwSPI(unsigned int Cmd){
   unsigned char s1,s2;
   unsigned int recv=0;
   LO_B(SCK);
   LO_B(nSEL);
   USICR=0x12;
   s1=(1<<USIWM0)|(0<<USICS0)|(1<<USITC);
   s2=(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK);
   USIDR=((Cmd>>8)&0xFF);
   USICR=s1;  USICR=s2;
   USICR=s1;  USICR=s2; 
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   recv=USIDR;
   USIDR=Cmd&0xFF;
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   USICR=s1;  USICR=s2;    
   recv=(recv<<8)+USIDR;
   USICR=0x00;
   HI_B(nSEL);
return recv;
}

[editovat] Vysílač

Po zapnutí napájení se vypnou všechny nepotřebné části procesoru, nastaví se přerušení na tlačítka a procesor i modul se přepne do režimu s nejnižší spotřebou (0,313±0,002 uA při napájení 2,59 V). Po zmáčknutí tlačítka se procesor probudí a podle zmáčknutého tlačítka zavolá z přerušení funkci TX, která nastaví modul a odvysílá kód zmáčknutého tlačítka. Poté se procesor i modul znovu uspí.

	#include <tiny2313.h>

	#define HI_B(x) PORTB |=  (1<<(x))
	#define LO_B(x) PORTB &= ~(1<<(x))
	#define SCK  7   // SPI clock
	#define SDI  6   // SPI Data input  
	#define SDO  5   // SPI Data output
	#define CS   4   // chip select
	#define IRQ  3   // interrupt
	#define LED  0   // red LED;

	unsigned int hwSPI(unsigned int Cmd){
	   unsigned char s1,s2;
	   unsigned int recv=0;
	   LO_B(SCK);
	   LO_B(CS);
	   USICR=0x12;
	   s1=(1<<USIWM0)|(0<<USICS0)|(1<<USITC);           
	   s2=(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK);
	   USIDR=((Cmd>>8)&0xFF);
	   USICR=s1;  USICR=s2;
	   USICR=s1;  USICR=s2; 
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   recv=USIDR;
	   USIDR=Cmd&0xFF;
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   recv=(recv<<8)+USIDR;
	   USICR=0x00;
	   HI_B(CS);
	return recv;
	}

	void TX(unsigned char btn){
		unsigned int k,st;
		unsigned char i;
		const unsigned char head[5]={0xAA,0xAA,0xAA,0x2D,0xD4};
		const unsigned char btn0[8]={62, 210,16,227,203,159,22, 66};
		const unsigned char btn1[8]={127,105,51,153,200,142,148,167};
		unsigned char *pbtn;
	    
		USICR=0x00; //vypne USI
		PORTB=0x14; //nastaví vstupy a výstupy 
		DDRB=0xD1;  
	    
		if (btn<3){
			if (btn==0){pbtn=btn0;}
			if (btn==1){pbtn=btn1;}
			HI_B(LED);
			hwSPI(0x80D8);//433 MHz
			hwSPI(0x8219);//TX
			hwSPI(0xA640);//nosná 434 MHz
			hwSPI(0xC647);//4.8kbps                                                             
			hwSPI(0x94A0);//134kHz,0dBm,-103dBm
			hwSPI(0xC2AC);//DQD4
			hwSPI(0xCA81);//FIFO8
			hwSPI(0xCED4);//SYNC=2DD4
			hwSPI(0xC483);
			hwSPI(0x9850);//MAX OUT
			hwSPI(0xCC77);
			hwSPI(0xE000);
			hwSPI(0xC800);
			hwSPI(0xC040); 
			hwSPI(0x0000);  
	        
			hwSPI(0xB8AA);  //zapisu dummy byte do registru pro TX
			hwSPI(0xB8AA);  //je to cast hlavicky
			hwSPI(0x8239);  //ET=1, zacnu vysílat
			for(i=2; i<5; i++){
				while(PINB&(1<<IRQ)){;}  //čeká až se vyprázdní zasobnik
				hwSPI(0xB800+head[i]);   //posílá hlavičku
			}
	        
			for(i=0; i<8; i++){
				while(PINB&(1<<IRQ)){;}     
				hwSPI(0xB800+pbtn[i]);   //posílá data
                        }
	        
			for(i=0; i<3; i++){
				while(PINB&(1<<IRQ)){;}
				hwSPI(0xB800+head[i]);   //posílá konec
			}
	                      
			hwSPI(0x8219);		//konec TX
			st=hwSPI(0x0000);	//stav
			hwSPI(0xB8AA);
	        
			if (st==0){			//je to OK
				for(k=0; k<60000; k++){;} //pozor na optimalizaci
				LO_B(LED);
				for(k=0; k<60000; k++){;} //trvání je libovolná, tak aby bylo vidět bliknutí
				HI_B(LED);
				for(k=0; k<60000; k++){;}
			}
		}                 
	         
		hwSPI(0x8201); //power down - sleep
		LO_B(LED);
		PORTB=0x00; // no pull-up
		DDRB=0x00;  //input
		return;
	}   

	//přerušení z INT0
	interrupt [EXT_INT0] void ext_int0_isr(void){
		TX(0);
	}

	//přerušení z INT1
	interrupt [EXT_INT1] void ext_int1_isr(void){
		TX(1);
	}

	void main(void){
		//#asm("cli"); //zakáže přerušení, překladač vloží do resetu sám
	    
		#pragma optsize-
		CLKPR=0x80; 
		CLKPR=0x03; //hodiny 1 MHz
		#ifdef _OPTIMIZE_SIZE_
		#pragma optsize+
		#endif

		PORTA=0x04; //pull-up u resetu
		DDRA=0x00;

		PORTB=0x00;
		DDRB=0x00;
	        
		PORTD=0x0C;  //pull-up u tlacitek
		DDRD=0x00;

		TCCR0A=0x00; //Časovač/čítač 0 - vypnuto
		TCCR0B=0x00;
		TCNT0=0x00;
		OCR0A=0x00;
		OCR0B=0x00;

		TCCR1A=0x00; //Časovač/čítač 0 - vypnuto
		TCCR1B=0x00;
		TCNT1H=0x00;
		TCNT1L=0x00;
		ICR1H=0x00;
		ICR1L=0x00;
		OCR1AH=0x00;
		OCR1AL=0x00;
		OCR1BH=0x00;
		OCR1BL=0x00;
	    
		MCUCR=0x00; //přerušení na INT0 a INT1, reaguje na log. 0
		GIMSK=0xC0; 
		GIFR=0xC0;

		TIMSK=0x00; //Časovače/čítače - vypnuto

		USICR=0x00; //USI - vypnuto

		UCSRB=0x00; //USART - vypnuto

		ACSR=0x80; //komparátor - vypnuto
		DIDR=0x00;

		MCUSR=0;  //příznaky resetů
		WDTCSR=0; //WatchDog - vypnuto
	    
		TX(3);  //uspí RFM12B

		#asm("sei") // povolí přerušení

		while (1){
			MCUCR=MCUCR|0b01110000; //power-down 
			#asm("sleep")			//přechod do režimu nízké spotřeby
			MCUCR=(MCUCR)&(0b11011111); 
		}
	}

[editovat] Přijímač

Hodně podobný jako vysílač, proto je tady méně komentářů. Je to funkční verze.

	#include <tiny2313.h>

	#define HI_B(x) PORTB |=  (1<<(x))
	#define LO_B(x) PORTB &= ~(1<<(x))
	#define SCK  7   // SPI clock
	#define SDI  6   // SPI Data input  
	#define SDO  5   // SPI Data output
	#define CS   4   // chip select
	#define IRQ  3   // interrupt
	#define LED1 1   // red LED;
	#define LED0 0   // red LED;

	unsigned int hwSPI(unsigned int Cmd){
	   unsigned char s1,s2;
	   unsigned int recv=0;
	   LO_B(SCK);
	   LO_B(CS);
	   USICR=0x12;
	   s1=(1<<USIWM0)|(0<<USICS0)|(1<<USITC);          
	   s2=(1<<USIWM0)|(0<<USICS0)|(1<<USITC)|(1<<USICLK);
	   USIDR=((Cmd>>8)&0xFF);
	   USICR=s1;  USICR=s2;
	   USICR=s1;  USICR=s2; 
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   recv=USIDR;
	   USIDR=Cmd&0xFF;
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   USICR=s1;  USICR=s2;    
	   recv=(recv<<8)+USIDR;
	   USICR=0x00;
	   HI_B(CS);
	return recv;
	}

	//přijímání dat
	unsigned char rfRecv() {
		unsigned int data;
		while(PINB&(1<<IRQ)){;}
		data = hwSPI(0xB000);
		return (data&0x00FF);
	}

	void main(void){
		#asm("cli")  
		#pragma optsize-
		CLKPR=0x80; 
		CLKPR=0x03; 
		#ifdef _OPTIMIZE_SIZE_
		#pragma optsize+
		#endif

		PORTA=0x04;
		DDRA=0x00;

		PORTB=0x00;
		DDRB=0x00;
	        
		PORTD=0x00; 
		DDRD=0x00;

		TCCR0A=0x00;
		TCCR0B=0x00;
		TCNT0=0x00;
		OCR0A=0x00;
		OCR0B=0x00;

		TCCR1A=0x00;
		TCCR1B=0x00;
		TCNT1H=0x00;
		TCNT1L=0x00;
		ICR1H=0x00;
		ICR1L=0x00;
		OCR1AH=0x00;
		OCR1AL=0x00;
		OCR1BH=0x00;
		OCR1BL=0x00;

		MCUCR=0x00; //nemá tlačítka - vypnuto
		GIMSK=0x00;

		TIMSK=0x00;

		USICR=0x00;

		UCSRB=0x00;

		ACSR=0x80;
		DIDR=0x00;

		MCUSR=0; 
		WDTCSR=0;    
	 
		//RX  
		PORTB=0x14; //nastavení pro RX
		DDRB=0xD3;   
	   
		HI_B(CS);
		hwSPI(0x0000);
		hwSPI(0x80D8);
		hwSPI(0x8201);//RX
		hwSPI(0xA640);
		hwSPI(0xC647);                                                          
		hwSPI(0x94A0);
		hwSPI(0xC2AC);
		hwSPI(0xCA81);
		hwSPI(0xCED4);
		hwSPI(0xC483);
		hwSPI(0x9850);
		hwSPI(0xCC77);
		hwSPI(0xE000);
		hwSPI(0xC800);
		hwSPI(0xC040); 
		hwSPI(0x0000); 
	           
		while (1){
			const unsigned char btn0[8]={62, 210,16,227,203,159,22, 66};
			const unsigned char btn1[8]={127,105,51,153,200,142,148,167};  
			unsigned char i,j,btnr[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
			unsigned int k;    
	        
			HI_B(LED0); HI_B(LED1);
			for (k=0; k<60000; k++) {;} 
			LO_B(LED0); LO_B(LED1);
	       
			hwSPI(0x8299);
			hwSPI(0xCA81); //FIFO po 8 bitech přerušení
			hwSPI(0xCA83); //FIFO reset
	       
 			for(j=0; j<8; j++){
				btnr[j]=rfRecv();
			}
	        
  			hwSPI(0x8201);
	        
			j=1; //porovnání přijatého kódu
 			for(i=0; i<8; i++){
				if(btn0[i]!=btnr[i]){j=0;}
			}
			if(j==1){HI_B(LED0);}
	        
			j=1; //porovnání přijatého kódu
			for(i=0; i<8; i++){
				if(btn1[i]!=btnr[i]){j=0;}
			}
			if(j==1){HI_B(LED1);}
	        
			for(k=0; k<60000; k++){;}
			for(k=0; k<60000; k++){;}
			for(k=0; k<60000; k++){;}
			for(k=0; k<60000; k++){;}
			LO_B(LED0);
			LO_B(LED1);
			for(k=0; k<60000; k++){;}
		}
 	}

[editovat] Úkol 1

Zde je řešení pro ATtiny2313. Místo A/D převodníku byl použit komparátor a časovač. Princip je v Application Note AVR400: Low Cost A/D Converter. Zapojení je na obrázku.


Soubor:Uk1.png


	.EQU SREG=0x3F
	.EQU __SRAM_START=0x0060
	.EQU __SRAM_END=0x00DF
	.EQU __DSTACK_SIZE=0x0020
	.EQU __HEAP_SIZE=0x0000
	.EQU __CLEAR_SRAM_SIZE=__SRAM_END-__SRAM_START+1

	.CSEG
	.ORG 0x00

	RJMP __RESET       ;INTERRUPT VECTORS
	RJMP 0x00
	RJMP _ext_int1_isr
	RJMP _timer1_capt_isr
	RJMP 0x00
	RJMP _timer1_ovf_isr
	RJMP _timer0_ovf_isr
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00
	RJMP 0x00

__RESET:
	CLI
	CLR  R30
	OUT  0x1C,R30      ;EECR=0
	OUT  0x35,R30      ;MCUCR=0

	LDI  R31,0x18      ;DISABLE WATCHDOG
	IN   R26,0x34      ;R26=MCUSR
	CBR  R26,8
	OUT  0x34,R26      ;MCUSR=R26
	OUT  0x21,R31      ;WDTCR=R31
	OUT  0x21,R30      ;WDTCR=R30

	LDI  R24,(14-2)+1  ;CLEAR R2-R14
	LDI  R26,2
__CLEAR_REG:
	ST   X+,R30
	DEC  R24
	BRNE __CLEAR_REG

	LDI  R24,__CLEAR_SRAM_SIZE   ;CLEAR SRAM
	LDI  R26,__SRAM_START
__CLEAR_SRAM:
	ST   X+,R30
	DEC  R24
	BRNE __CLEAR_SRAM

	LDI  R30,LOW(0)    ;GPIOR0-GPIOR2 INITIALIZATION
	OUT  0x13,R30      ;GPIOR0=0 
	OUT  0x14,R30      ;GPIOR1=0
	OUT  0x15,R30      ;GPIOR2=0

	LDI  R30,LOW(__SRAM_END-__HEAP_SIZE)  ;HARDWARE STACK POINTER INITIALIZATION
	OUT  0x3D,R30      ;SPL=R30
	LDI  R28,LOW(__SRAM_START+__DSTACK_SIZE) ;DATA STACK POINTER INITIALIZATION

	RJMP _main

 
_timer1_ovf_isr:
	ST   -Y,R30
	IN   R30,SREG
	ST   -Y,R30
      
	LDI  R30,LOW(10)   ;if (pwm2==10){
	CP   R30,R4
	BRNE _if1
	SBI  0x18,2        ;HIB(CAD);
	IN   R30,0x39      ;TIMSK=TIMSK|0x08
	ORI  R30,8
	OUT  0x39,R30
	CLR  R4            ;pwm2=0
_if1:
	INC  R4            ;pwm2++

	LD   R30,Y+
	OUT  SREG,R30
	LD   R30,Y+
	RETI


_timer1_capt_isr:
	ST   -Y,R30
	IN   R30,SREG
	ST   -Y,R30

	IN   R30,0x39      ;TIMSK=TIMSK&0xF7
	ANDI R30,0XF7
	OUT  0x39,R30
	IN   R30,0x24      ;OCR1BL=ICR1L
	OUT  0x28,R30
	CBI  0x18,2        ;LOB(CAD)

	LD   R30,Y+
	OUT  SREG,R30
	LD   R30,Y+
	RETI


_ext_int1_isr:
	ST   -Y,R30
	IN   R30,SREG
	ST   -Y,R30

	SBI  0x12,5        ;HI(LED1)
     
_while2:
	IN   R30,0x16      ;while(PINB&(1<<TL)==0){;}
	ANDI R30,LOW(0x0)
	BRNE _while2
    
	CLR  R2            ;cas=0
	CLR  R3            ;cas=0
	LDI  R30,LOW(3)    ;Timer 0
	OUT  0x30,R30      ;TCCR0A=0x03
	LDI  R30,LOW(11) 
	OUT  0x33,R30      ;TCCR0B=0x0B
	LDI  R30,LOW(0)  
	OUT  0x32,R30      ;TCNT0=0x00;
	LDI  R30,LOW(78)   
	OUT  0x36,R30      ;OCR0A=0x4E
	OUT  0x3C,R30      ;OCR0B=0x4E
	IN   R30,0x39      ;TIMSK=TIMSK|0x02
	ORI  R30,2
	OUT  0x39,R30

	LD   R30,Y+
	OUT  SREG,R30
	LD   R30,Y+
	RETI


_timer0_ovf_isr:
	ST   -Y,R30
	ST   -Y,R31
	IN   R30,SREG
	ST   -Y,R30

	MOVW R30,R2        ;cas++;
	ADIW R30,1
	MOVW R2,R30

	LDI  R30,LOW(1002) ;if (cas==PLN)
	LDI  R31,HIGH(1002)
	CP   R30,R2
	CPC  R31,R3
	BRNE _if2
	LDI  R30,LOW(35)   ;if splneno
	OUT  0x30,R30      ;TCCR0A=0x23
	CLR  R5            ;pwm=0;

_if2:
	LDI  R30,LOW(1002) ;if (cas>PLN)
	LDI  R31,HIGH(1002)
	CP   R30,R2
	CPC  R31,R3
	BRSH _if4
         
	INC  R5            ;pwm++;

	LDI  R30,LOW(5)    ;if (pwm==DSV)
	CP   R30,R5
	BRNE _if3
	CLR  R5            ;pwm=0
	IN   R30,0x3C      ;OCR0B--
	SUBI R30,LOW(1)
	OUT  0x3C,R30

_if3:
	IN   R30,0x3C      ;if (OCR0B==0)
	CPI  R30,0
	BRNE _if5

	IN   R30,0x39      ;TIMSK=TIMSK&0xFD
	ANDI R30,0xFD
	OUT  0x39,R30
	LDI  R30,LOW(0)
	OUT  0x30,R30      ;TCCR0A=0x00
	OUT  0x33,R30      ;TCCR0B=0x00
	OUT  0x32,R30      ;TCNT0=0x00
	OUT  0x36,R30      ;OCR0A=0x00
	OUT  0x3C,R30      ;OCR0B=0x00
	CBI  0x12,5        ;LO(LED1)
_if5:
_if4:
	LD   R30,Y+
	OUT  SREG,R30
	LD   R31,Y+
	LD   R30,Y+
	RETI
    
    
_main:
	LDI  R30,LOW(128)  ;hodiny
	OUT  0x26,R30      ;CLKPR=0x80
	LDI  R30,LOW(3)    
	OUT  0x26,R30      ;CLKPR=0x03

	LDI  R30,LOW(0)   
	OUT  0x1B,R30      ;PORTA=0x00   all in, high z
	OUT  0x1A,R30      ;DDRA=0x00

	OUT  0x18,R30      ;PORTB=0x00   4 a 2 je out 0, ostatní in  high z
	LDI  R30,LOW(20)  
	OUT  0x17,R30      ;DDRB=0x14

	LDI  R30,LOW(8)      
	OUT  0x12,R30      ;PORTD=0x08  5 je out 0, 3 je in pull-up, ostatní in high z
	LDI  R30,LOW(32)   
	OUT  0x11,R30      ;DDRD=0x20

	LDI  R30,LOW(0)    ;Timer 0
	OUT  0x30,R30      ;TCCR0A=0x00
	OUT  0x33,R30      ;TCCR0B=0x00
	OUT  0x32,R30      ;TCNT0=0x00
	OUT  0x36,R30      ;OCR0A=0x00
	OUT  0x3C,R30      ;OCR0B=0x00

	LDI  R30,LOW(35)   ;Timer 1
	OUT  0x2F,R30      ;TCCR1A=0x23
	LDI  R30,LOW(91)   
	OUT  0x2E,R30      ;TCCR1B=0x5B
	LDI  R30,LOW(0)    
	OUT  0x2D,R30      ;TCNT1H=0x00
	OUT  0x2C,R30      ;TCNT1L=0x00
	OUT  0x25,R30      ;ICR1H=0x00
	OUT  0x24,R30      ;ICR1L=0x00
	OUT  0x2B,R30      ;OCR1AH=0x00
	LDI  R30,LOW(78)   
	OUT  0x2A,R30      ;OCR1AL=0x4E
	LDI  R30,LOW(0)    
	OUT  0x29,R30      ;OCR1BH=0x00
	OUT  0x28,R30      ;OCR1BL=0x00

	LDI  R30,LOW(128)  ;INT1
	OUT  0x3B,R30      ;GIMSK=0x80
	LDI  R30,LOW(0)
	OUT  0x35,R30      ;MCUCR=0x00
	LDI  R30,LOW(128)  
	OUT  0x3A,R30      ;EIFR=0x80

	OUT  0x39,R30      ;TIMSK=0x80 Timer interrupt

	LDI  R30,LOW(0)    ;USI off
	OUT  0xD,R30       ;USICR=0x00
	
        OUT  0xA,R30       ;UCSRB=0x00 USART off

	LDI  R30,LOW(4)    ;Analog Comparator
	OUT  0x8,R30       ;ACSR=0x04
	LDI  R30,LOW(3)    ;Digital input buffer
	OUT  0x1,R30       ;DIDR=0x03

	CLR  R4            ;pwm2=0
	sei                ;Global enable interrupts

_while1:
	IN   R30,0x35      ;MCUCR=MCUCR|0b00100000
	ORI  R30,0x20
	OUT  0x35,R30
	sleep              ;idle
	IN   R30,0x35      ;MCUCR=(MCUCR)&(0b11011111)
	ANDI R30,0xDF
	OUT  0x35,R30
	RJMP _while1
_END:
	RJMP _END

[editovat] Cvičení

  1. include <avr/io.h>


/*unsigned char cti(unsigned long int adr){ PORTB|=(adr>>15)&31; *(adr&0x7FFF)=data; return data; }*/

void zapis(unsigned long int adr, unsigned char data){ PORTB|=(adr>>15)&31; *(unsigned char *)(int)(adr&0x7FFF)=data; return; }


int main(void){ unsigned char d; //d=cti(254697); zapis(100000,31); return 0; }


[editovat] PWM ovládaná maticovou klávesnicí přes přerušení s úsporným režimem

//**************************************************************//

   .LISTMAC
   .EQU UDRE=0x5
   .EQU RXC=0x7
   .EQU USR=0xB
   .EQU UDR=0xC
   .EQU EERE=0x0
   .EQU EEWE=0x1
   .EQU EEMWE=0x2
   .EQU EECR=0x1C
   .EQU EEDR=0x1D
   .EQU EEARL=0x1E
   .EQU WDTCR=0x21
   .EQU MCUSR=0x34
   .EQU MCUCR=0x35
   .EQU SPL=0x3D
   .EQU SREG=0x3F
   .EQU GPIOR0=0x13
   .EQU GPIOR1=0x14
   .EQU GPIOR2=0x15
   .DEF R0X0=R0
   .DEF R0X1=R1
   .DEF R0X2=R2
   .DEF R0X3=R3
   .DEF R0X4=R4
   .DEF R0X5=R5
   .DEF R0X6=R6
   .DEF R0X7=R7
   .DEF R0X8=R8
   .DEF R0X9=R9
   .DEF R0XA=R10
   .DEF R0XB=R11
   .DEF R0XC=R12
   .DEF R0XD=R13
   .DEF R0XE=R14
   .DEF R0XF=R15
   .DEF R0X10=R16
   .DEF R0X11=R17
   .DEF R0X12=R18
   .DEF R0X13=R19
   .DEF R0X14=R20
   .DEF R0X15=R21
   .DEF R0X16=R22
   .DEF R0X17=R23
   .DEF R0X18=R24
   .DEF R0X19=R25
   .DEF R0X1A=R26
   .DEF R0X1B=R27
   .DEF R0X1C=R28
   .DEF R0X1D=R29
   .DEF R0X1E=R30
   .DEF R0X1F=R31
   .EQU __SRAM_START=0x0060
   .EQU __SRAM_END=0x00DF
   .EQU __DSTACK_SIZE=0x0020
   .EQU __HEAP_SIZE=0x0000
   .EQU __CLEAR_SRAM_SIZE=__SRAM_END-__SRAM_START+1
NAME DEFINITIONS FOR GLOBAL VARIABLES ALLOCATED TO REGISTERS
   .DEF _tl=R3
GPIOR0-GPIOR2 INITIALIZATION VALUES
   .EQU __GPIOR0_INIT=0x00
   .EQU __GPIOR1_INIT=0x00
   .EQU __GPIOR2_INIT=0x00
   .CSEG
   .ORG 0x00
START OF CODE MARKER

__START_OF_CODE:

INTERRUPT VECTORS
   RJMP __RESET
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP _pin_change_isr0
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00
   RJMP 0x00

__RESET:

   CLI
   CLR  R30
   OUT  EECR,R30
   OUT  MCUCR,R30
DISABLE WATCHDOG
   LDI  R31,0x18
   IN   R26,MCUSR
   CBR  R26,8
   OUT  MCUSR,R26
   OUT  WDTCR,R31
   OUT  WDTCR,R30
CLEAR R2-R14
   LDI  R24,(14-2)+1
   LDI  R26,2

__CLEAR_REG:

   ST   X+,R30
   DEC  R24
   BRNE __CLEAR_REG
CLEAR SRAM
   LDI  R24,__CLEAR_SRAM_SIZE
   LDI  R26,__SRAM_START

__CLEAR_SRAM:

   ST   X+,R30
   DEC  R24
   BRNE __CLEAR_SRAM
GPIOR0-GPIOR2 INITIALIZATION
   LDI  R30,__GPIOR0_INIT
   OUT  GPIOR0,R30
   ;__GPIOR1_INIT = __GPIOR0_INIT
   OUT  GPIOR1,R30
   ;__GPIOR2_INIT = __GPIOR0_INIT
   OUT  GPIOR2,R30
HARDWARE STACK POINTER INITIALIZATION
   LDI  R30,LOW(__SRAM_END-__HEAP_SIZE)
   OUT  SPL,R30
DATA STACK POINTER INITIALIZATION
   LDI  R28,LOW(__SRAM_START+__DSTACK_SIZE)
   RJMP _main
   .ESEG
   .ORG 0
   .DSEG
   .ORG 0x80
   .CSEG
  1. include <tiny2313.h>
   #ifndef __SLEEP_DEFINED__
   #define __SLEEP_DEFINED__
   .EQU __se_bit=0x20
   .EQU __sm_mask=0x50
   .EQU __sm_powerdown=0x10
   .EQU __sm_standby=0x40
   .SET power_ctrl_reg=mcucr
   #endif
unsigned char tl;
// Pin change 0-7 interrupt service routine
   .CSEG

_pin_change_isr0:

   ST   -Y,R0
   ST   -Y,R26
   ST   -Y,R30
   IN   R30,SREG
   ST   -Y,R30
   
   ST   -Y,R19
   ST   -Y,R18
   ST   -Y,R17
   ST   -Y,R16
   
   ;unsigned char col->R17, row->R16, i->R19;
   IN   R30,0x18    ;col=PORTB>>4; //&0xF0;
   SWAP R30
   ANDI R30,0xF
   MOV  R17,R30
   ;0-3 row, 4-7 columb     
   LDI  R30,LOW(15)  ;PORTB=0x0F  7 lg0, 6 lg0, 5 lg0, 4 lg0, 3 PU, 2 PU, 1 PU, 0 PU
   OUT  0x18,R30
   LDI  R30,LOW(240) ;DDRB=0xF0   7 Out, 6 Out, 5 Out, 4 Out, 3 In, 2 In, 1 In, 0 In
   OUT  0x17,R30
    
   IN   R30,0x18     ;row=PORTB&0x0F
   ANDI R30,LOW(0xF)
   MOV  R16,R30
    
   ;0-3 row, 4-7 columb swap
   LDI  R30,LOW(240) ;PORTB=0xF0  7 PU, 6 PU, 5 PU, 4 PU, 3 lg0, 2 lg0, 1 lg0, 0 lg0
   OUT  0x18,R30
   LDI  R30,LOW(15)  ;DDRB=0x0F   7 In, 6 In, 5 In, 4 In, 3 Out, 2 Out, 1 Out, 0 Out
   OUT  0x17,R30
    
   ;zero - button push
   LDI  R19,LOW(0)  ;i=0 ... for(i=0;i<4;i++){

_FOR:

   CPI  R19,4      ;compare  i<4
   BRLO PC+2       ;if lower
   RJMP _AfterFor  ;end for
        
   SBRC R17,0      ;if((col&1)==0) {break;}  Skip if Bit in Register is Cleared
   RJMP _CONTINUE  
   RJMP _AfterFor  ;break 

_CONTINUE:

   LSR  R17        ;col=col>>1
   SUBI R19,-1     ;i++  //nad tim _0x3:
   RJMP _FOR

_AfterFor:

   MOV  R17,R19    ;col=i
   
   LDI  R19,LOW(0)  ;i=0 ... for(i=0;i<4;i++){

_FOR2:

   CPI  R19,4      ;compare  i<4
   BRLO PC+2       ;if lower
   RJMP _AfterFor2 ;end for
        
   SBRC R16,0      ;if((row&1)==0) {break;}  Skip if Bit in Register is Cleared
   RJMP _CONTINUE2
   RJMP _AfterFor2

_CONTINUE2:

   LSR  R16       ;row=row>>1
   SUBI R19,-1    ;i++  //nad tim _0x7:
   RJMP _FOR2

_AfterFor2:

   MOV  R16,R19   ;row=i

MOV R30,R16  ;tl=row<<2 LSL R30 LSL R30 MOV R3,R30 ADD R3,R17  ;tl=tl+col

   MOV  R30,R3    ;OCR0B=(tl<<1)+tl; //tl*3
   LSL  R30       ;PWM 
   ADD  R30,R3
   OUT  0x3C,R30


   LDD  R19,Y+3
   LDD  R18,Y+2
   LDD  R17,Y+1
   LD   R16,Y
   
   ADIW R28,4
   LD   R30,Y+
   OUT  SREG,R30
   LD   R30,Y+
   LD   R26,Y+
   LD   R0,Y+
   RETI


_main:  ;void main(void){

   LDI  R30,LOW(0)
   OUT  0x1B,R30     ;PORTA=0x00
   OUT  0x1A,R30     ;DDRA=0x00 
   
   OUT  0x12,R30     ;PORTD=0x00
   LDI  R30,LOW(32)  ;DDRD=0x20;  //pin 5 - Out PWM
   OUT  0x11,R30
   
   LDI  R30,LOW(240) ;PORTB=0xF0  //7 PU, 6 PU, 5 PU, 4 PU, 3 lg0, 2 lg0, 1 lg0, 0 lg0
   OUT  0x18,R30
   LDI  R30,LOW(15)  ;DDRB=0x0F   //7 In, 6 In, 5 In, 4 In, 3 Out, 2 Out, 1 Out, 0 Out
   OUT  0x17,R30
   
   ;Interrupt on pins PCINT0-7
   LDI  R30,LOW(32)   ;GIMSK=0x20
   OUT  0x3B,R30
   LDI  R30,LOW(0)    ;MCUCR=0x00
   OUT  0x35,R30
   LDI  R30,LOW(240)  ;PCMSK=0xF0
   OUT  0x20,R30
   LDI  R30,LOW(32)   ;EIFR=0x20
   OUT  0x3A,R30
   ;Mode: Fast PWM top=OCR0A   OC0B output
   LDI  R30,LOW(35)     ;TCCR0A=0x23
   OUT  0x30,R30
   LDI  R30,LOW(9)      ;TCCR0B=0x09
   OUT  0x33,R30
   LDI  R30,LOW(0)      ;TCNT0=0x00
   OUT  0x32,R30
   LDI  R30,LOW(48)     ;OCR0A=0x30 perioda 48 - 1 MHz / 48 = 20,83 kHz
   OUT  0x36,R30
   OUT  0x3C,R30        ;OCR0B=0x30; //počet taktů s log. 1, start maximum
   LDI  R30,LOW(0)      ;TIMSK=0x00;
   OUT  0x39,R30
   sei                  ;Global enable interrupts

_WHILE:  ;while (1){

   IN   R30,0x35        ;MCUCR=MCUCR|0b00100000
   ORI  R30,0x20
   OUT  0x35,R30
   sleep
   IN   R30,0x35        ;MCUCR=(MCUCR)&(0b11011111)
   ANDI R30,0xDF
   OUT  0x35,R30
   RJMP _WHILE ;while } 

_END:

   RJMP _END
   .CSEG

__END_OF_CODE:  ;END OF CODE MARKER

//**************************************************************//

Osobní nástroje