logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Attiny2313][C]dioda rgb, mój program do robienia tęczy

Sinistra 20 Maj 2008 20:06 4797 15
  • #1 5161759
    Sinistra
    Poziom 14  
    Witam,
    Oto mój pierwszy program na mikrokontroler. Dopiero co dostałem USBasp programator i chcę sobie zrobić tęczowe podświetlenie do myszki komputera. Napisałem program, ale nie wiem czy mi wystartuje. Bardzo proszę o uwagi, spodziewam sie dużo bałaganu w tym. Aha, zrobiłem tak, że co dwa cykle przejścia kolorów, jest jeden cykl białego, tak, żeby fioletowy sie mógł wyświetlać.
    Mam zamiar użyć: AT90S2313-4SC.

    Cytat:

    /*Wojciech Marcinek, 20 Maj 2008, Kolorowe LED*/
    #include <io.h>
    #include <delay.h>
    #include <stdio.h>

    #define red PB.0
    #define blue PB.1
    #define green PB.2
    #define F_CPU 4

    int main (void)
    {
    while(1)
    {
    green = 0xff;
    red = 0xff; /*białe*/
    blue = 0xff;
    void _delay_ms (100); /* przerwa 100 milisekund*/

    while (red != 0xff && blue != 0x00 && green != 0x00) /*aż czerwona sie zaświeci*/
    {
    void _delay_ms (10);
    -- blue; /* niebieska wył. i zielona też*/
    -- green;
    }
    green = 0x00; /*upewniam sie że obie diody zgasły*/
    blue = 0x00;
    void _delay_ms (100);

    while (red != 0x00 && blue != 0x00 && green != 0xff) /*aż zielona sie zaświeci*/
    {
    void _delay_ms (10);
    -- red; /*czerwona wył, zielona wł.*/
    ++ green;
    }
    red = 0x00;
    green = 0xff;
    void _delay_ms (100);

    while (red != 0x00 && blue != 0xff && green != 0x00) /* aż niebieska sie zaświeci */
    {
    void _delay_ms (10);
    ++ blue;
    -- green
    }
    blue = 0xff; /*nieb. wł., ziel. wył.*/
    green = 0x00;
    void _delay_ms (100);

    while (red != 0xff && blue != 0x00 && green != 0x00) /* aż czerwona sie zaświeci, drugi raz*/
    {
    void _delay_ms (10);
    ++ red;
    -- blue;
    }
    red = 0xff; /*czerw. wł., nieb wył.*/
    blue = 0x00;
    void _delay_ms (100);

    while (red != 0x00 && blue != 0x00 && green != 0xff) /*aż zielona sie zaświeci*/
    {
    void _delay_ms (10);
    -- red; /*czerwona wył, zielona wł.*/
    ++ green;
    }
    red = 0x00;
    green = 0xff;
    void _delay_ms (100);

    while (red != 0x00 && blue != 0xff && green != 0x00) /* aż niebieska sie zaświeci */
    {
    void _delay_ms (10);
    ++ blue;
    -- green
    }
    blue = 0xff; /*nieb. wł., ziel. wył.*/
    green = 0x00;
    void _delay_ms (100);

    while (red != 0xff && blue != 0xff && grteen != 0xff)
    {
    void _delay_ms (10);
    ++ green;
    ++ red;
    }
    }
    }



    Sorki że długie, ale chce przedstawić całość.
    Sinistra
  • #2 5162643
    Konto nie istnieje
    Poziom 1  
  • #3 5162711
    Sinistra
    Poziom 14  
    używam avr studio 4.13, ale tak czy inaczej mi nie widzi USBasp. Teraz już rozumiem z tymi nawiasami, ale to z PWM nie wiem o co chodzi, może jest inny sposób do kontrolowania tymi diodami?

    P.S. tyle operatorów logicznych używałem, żebym lepiej mógł sie poruszać po tekście.
  • #4 5163592
    Konto nie istnieje
    Poziom 1  
  • #5 5164005
    iwan3000
    Poziom 16  
    AT90S2313 już nie produkują. Przejdź na ATtiny2313
  • #7 5182024
    Sinistra
    Poziom 14  
    wrzucam kod:
    /*Wojciech Marcinek, 20 May 2008, color LEDs*/
    #include <avr/io.h>
    
    #define blue OCR0A
    #define red OCR0B
    #define green OCR1BL
    
    
    
    int main (void)
    {
    	int i;
    	unsigned int r, g, b;
    	
    	DDRB=0xff;
    	DDRD=0xff;
    	TCCR0A = (1 << COM0B1)|(1 << COM0B0)|(1 << COM0A1)|(1 << COM0A0)|(1 << WGM01)|(1 << WGM00); 
    	TCCR0B = (1 << CS00); 
    	TCCR1A = (1 << COM1B1)|(1 << COM1B0)|(1 << WGM10); 
    	TCCR1B = (1 << WGM12)|(1 << CS10); 
    	OCR1BH = 0; 
    		
    	red=0xff;
    	green=0xff;
    	blue=0xff;
    	for(i=100;i!=0;--i);
    	for(i=100;i!=0;--i);
    
    	while(1)
    	{
    	while((green!=0)&& (blue!=0))
    		{ --green;
    		--blue;
    		for(i=1500;i!=0;--i) ; }
    	/*--g--b*/
    	while (green!=0x9f)
    		{ ++green;
    		for(i=1500;i!=0;--i) ; }
    	/*++g*/
    	while(red!=0)
    		{ --red;
    		for(i=1500;i!=0;--i) ; }
    	/*--r*/
    	while(blue!=0x9f)
    		{ ++blue;
    		for(i=1500;i!=0;--i) ;}
    	/*++b*/ 
    	while(green!=0)
    		{ --green;
    		for(i=1500;i!=0;--i) ; }
    	/*--g*/
    	while(red!=0x9f)
    		{ ++red;
    		for(i=1500;i!=0;--i) ;} 
    	/*++r*/
    	while (green!=0x9f)
    		{ ++green;
    		for(i=1500;i!=0;--i) ; }
    	/*++g*/
    	while((red!=0) && (blue!=0))
    		{ --red;
    		--blue;
    		for(i=1500;i!=0;--i) ; }
    	/*--r--b*/
    	while(blue!=0x9f)
    		{ ++blue;
    		for(i=1500;i!=0;--i) ;}
    	/*++b*/ 
    	while(green!=0)
    		{ --green;
    		for(i=1500;i!=0;--i) ; }
    	/*--g*/
    	while(red!=0x9f)
    		{ ++red;
    		for(i=1500;i!=0;--i) ;} 
    	/*++r*/
    	while(blue!=0)
    		{ --blue;
    		for(i=1500;i!=0;--i) ; }
    	/*--b*/
    	while (green!=0x9f)
    		{ ++green;
    		for(i=1500;i!=0;--i) ; }
    	/*++g*/
    	while(blue!=0x9f)
    		{ ++blue;
    		for(i=1500;i!=0;--i) ;}
    	/*++b*/ 
    	while((red!=0) && (green!=0))
    		{ --red;
    		--green;
    		for(i=1500;i!=0;--i) ; }
    	/*--r--g*/
    	while(red!=0x9f)
    		{ ++red;
    		for(i=1500;i!=0;--i) ;} 
    	/*++r*/
    	while(blue!=0)
    		{ --blue;
    		for(i=1500;i!=0;--i) ; }
    	/*--b*/
    	while (green!=0x9f)
    		{ ++green;
    		for(i=1500;i!=0;--i) ; }
    	/*++g*/
    	while(red!=0)
    		{ --red;
    		for(i=1500;i!=0;--i) ; }
    	/*--r*/
    	while(blue!=0x9f)
    		{ ++blue;
    		for(i=1500;i!=0;--i) ;}
    	/*++b*/ 
    	while(red!=0x9f)
    		{ ++red;
    		for(i=1500;i!=0;--i) ;} 
    	/*++r*/
    
    	}
    }
    pomóżcie jak to skrócić, bo mi 1.4 KB zajmuje, a ja chce jeszcze trochę interruptsów włożyć do tej kostki :?:
  • #8 5185191
    Konto nie istnieje
    Poziom 1  
  • #9 5186763
    Sinistra
    Poziom 14  
    Czyli raczej powinienem używać wielu funkcji zamiast jednej wielkiej?
    O tym nie myślałem, ale zdecydowałem sie skrócić pętle kolorów do tylko 7 kroków.
    while(1)
    	{
    	while((green!=0)&& (blue!=0))
    		{ --green;
    		--blue;
    		for(i=100;i!=0;--i) ; }
    	/*--g--b*/
    	while (green!=0xfa)
    		{ ++green;
    		for(i=100;i!=0;--i) ; }
    	/*++g*/
    	while(red!=0)
    		{ --red;
    		for(i=100;i!=0;--i) ; }
    	/*--r*/
    	while(blue!=0xfa)
    		{ ++blue;
    		for(i=100;i!=0;--i) ;}
    	/*++b*/ 
    	while(green!=0)
    		{ --green;
    		for(i=100;i!=0;--i) ; }
    	/*--g*/
    	while(red!=0xfa)
    		{ ++red;
    		for(i=100;i!=0;--i) ;} 
    	/*++r*/
    	while (green!=0xfa)
    		{ ++green;
    		for(i=100;i!=0;--i) ; }
    	for(i=1000;i!=0;--i);
    	/*++g*/	
    	}

    teraz zajmuje juz tylko 700KB:D
    Spróbuje zrobić jeszcze te funkcje

    Dodano po 34 [minuty]:

    Dobra zrobiłem z tego trochę porządku.
    jest tak:
    void inicjacja (void)
    {
    /*ustawianie rejestrów*/
    	/*PWM+timery*/
    	TCCR0A = (1<<COM0A1) | (1<<COM0A0) | (1<<COM0B1) | (1<<COM0B0) | (1<<WGM01) | (1<<WGM00); 
    	TCCR0B = (1<<CS00); 
    	TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(1<<WGM10); 
    	TCCR1B = (1<<WGM12)|(1<<CS10);
    	
    	/*łoczdog i przerwwania+timery*/
    	WDTCSR = (1<<WDIE) | (1<<WDP3) | (1<<WDIF);
    	MCUCR = (1<<ISC10);
    	SREG = (1<<7);
    	GIMSK = (1<<INT1);
    	EIFR = (1<<INTF1);
    	DDRB = 0xff;
    	DDRD = 0xff;
    }
    
    void czekaj(void)
    {
    unsigned char i;
    for(i=100;i!=0;--i) ;
    }

    a potem te kolory (nie we funkcji jeszcze) i interrupts:
    SIGNAL (SIG_WDT_OVERFLOW) /*w tym miejscu kompilator chce żebym postawił średnik???*/
    {
    WDTCSR = 0;
    red=0;
    green=0;
    blue=0;
    while(1){}
    }
    	
    INTERRUPT(INT1) /*w tym miejscu też chce średnik???*/
    {
    red=255;
    blue=green=0;
    while(1){}
    }

    No i z tymi interrupts zaczynają sie problemy.
    kompilator ich nie chce:

    P.S. linia 78 to ta z watchdog interrupt, a 88 to klamra za (INT1)
  • #10 5186999
    Konto nie istnieje
    Poziom 1  
  • #11 5187405
    Sinistra
    Poziom 14  
    /*Wojciech Marcinek, 20 May 2008, color LEDs*/
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #define red OCR0A
    #define green OCR0B
    #define blue OCR1B
    
    
    void inicjacja (void)
    {
    /*ustawianie rejestrów*/
    	/*PWM+timery*/
    	TCCR0A = (1<<COM0A1) | (1<<COM0A0) | (1<<COM0B1) | (1<<COM0B0) | (1<<WGM01) | (1<<WGM00); 
    	TCCR0B = (1<<CS00); 
    	TCCR1A = (1<<COM1B1)|(1<<COM1B0)|(1<<WGM10); 
    	TCCR1B = (1<<WGM12)|(1<<CS10);
    	
    	/*łoczdog i przerwwania+timery*/
    	WDTCSR = (1<<WDIE) | (1<<WDP3) | (1<<WDIF);
    	MCUCR = (1<<ISC10);
    	SREG = (1<<7);
    	GIMSK = (1<<INT1);
    	EIFR = (1<<INTF1);
    	DDRB = 0xff;
    	DDRD = 0xff;
    }
    
    void czekaj(void)
    {
    unsigned char i;
    for(i=100;i!=0;--i) ;
    }
    
    int main (void)
    {
    inicjacja();
    	red=0xff;
    	green=0xff;
    	blue=0xff;
    	czekaj();
    
    	while(1)
    	{
    	while((green!=0)&& (blue!=0))
    		{ --green;
    		--blue;
    		czekaj(); }
    	while (green!=0xfa)
    		{ ++green;
    		czekaj(); }
    	while(red!=0)
    		{ --red;
    		czekaj(); }
    	while(blue!=0xfa)
    		{ ++blue;
    		czekaj(); }
    	while(green!=0)
    		{ --green;
    		czekaj(); }
    	while(red!=0xfa)
    		{ ++red;
    		czekaj(); }
    	while (green!=0xfa)
    		{ ++green;
    		czekaj(); }
    	czekaj();
    
    	}
    
    SIGNAL (SIG_WDT_OVERFLOW); /*w tym miejscu kompilator chce żebym postawił średnik???*/
    {
    WDTCSR = 0;
    red=0;
    green=0;
    blue=0;
    while(1){}
    }
    	
    INTERRUPT(SIG_INTERRUPT1); /*w tym miejscu też chce średnik??? poprawiłem*/
    {
    red=255;
    blue=0;
    green=0; /*poprawiłem ,dzięki*/
    while(1){}
    }
    
    }

    Jeszcze jedna uwaga: według WDP3 czyli co 4 sekundy timer watchdog daje sygnał interrupt, i program main idzie od początku, czyli zaświecają się wszystkie kolory. Tak w kółko.

    PS. musiałem dodać średniki, bo kompilator nie chciał skompilować.

    Dodano po 59 [minuty]:

    a,
    kiedy naciskam
    przycisk od INT1, program main idzie też od początku
    ta wersja programu zajmuje 478 bytes. :?: :idea: :arrow: odziwo
  • Pomocny post
    #12 5188081
    Konto nie istnieje
    Poziom 1  
  • #13 5188240
    Sinistra
    Poziom 14  
    ten reset w watchdogu był tylko poto,, żebym sie nauczył obsługiwać tę funkcję ( bo to pierwszy raz gdy sam napisałem program używając obsługi aż tylu rejestrów. Ogólnie to pomysł był, żeby do myszki komputerowej włożyć taki moduł, dzięki czemu kolor sie będzie cały czas zmieniał. Interrupts będą działały jako funkcje takie jak przyspieszanie, albo wyłączanie tej tęczy.

    Dodano po 1 [godziny] 24 [minuty]:

    Jeszcze jedna rzecz:
    Gdy wyłączę watchdoga, bo w sumie mi jest nie potrzebny do tej myszki, chcę skonfigurować INT1 i 0 aby kolejno: przyspieszały, i zwalniały zmienianie kolorów.
    napisałem tak:
    void czekaj(d)
    {
    unsigned int i;
    for(i=d;i!=0;--i) ;
    }
    unsigned int c=100;
    int main (void)
    {
    .....
    potem jest funkcja main, i w każdej funkcji czekaj dałem:
    .
    potem przerwania zmieniłem na:
    INTERRUPT1(SIG_INTERRUPT1)
    {
    c=c+15;
    }
    INTERRUPT0(SIG_INTERRUPT0)
    {
    c=c-15;
    }
    
    .
    rejestry zmieniłem:
    	MCUCR = (1<<ISC10) | (1<<ISC00);
    	SREG = (1<<7);
    	GIMSK = (1<<INT1) | (1<<INT0);
    	EIFR = (1<<INTF1) | (1<<INTF0);

    No i nie działa, Gdy naciskam któryś z INTx, main startuje od początku, ale prędkość sie nie zmienia.
  • #14 5189617
    Konto nie istnieje
    Poziom 1  
  • #15 5189816
    Sinistra
    Poziom 14  
    gdy była pętla nieskończona, to sie nie zawieszał poprostu szedł od początku. Czyli ja mam zrobić coś na zasadzie watchdoga, że gdy nacisnę przycisk, timer np 8 bit sie włącza, i po 80ms generuje przerwanie, ale od timera nie od INT1/0. Ale skoro funkcja od INTERRUPT1 i 0 mi nie działa, to jak mam włączyć timer 8 bit, żeby liczył ten czas?

    Dodano po 2 [minuty]:

    a funkcja sei(); jest równ:
    SREG = (1<<7)

    czyli bit I rejestru SREG

    Dodano po 32 [minuty]:

    jeszcze jedna sprawa: ustawiłem tak, żeby przerwanie było generowane gdy stan pinie INT1/0 jest "rising edge", czyli jakbym trzymał ten przycisk przez 1 sekundę to interrupt byłby tylko przez pierwszy cykl procesora. Mogę zrobi by interrupt był na low level, wtedy będzie generowany przez cały czas trzymania guzika...chyba :?:
  • #16 5219094
    Sinistra
    Poziom 14  
    dobra, zrobiłem, miałem dac opóźnienia _delay_loop_2() żeby zadziałało. Jest ok.

    P>S> musiałem też zdefiniowac OPTIMIZE s
REKLAMA