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

[ATtiny2313][C] Generator impulsów prostokątnych

kwartet 18 Sty 2010 01:43 3630 7
  • #1 7552563
    kwartet
    Poziom 11  
    Witam. To mój pierwszy projekt jeśli chodzi o avr, prosiłbym o przegląd kodu i ewentualne poprawki, chętnie dowiem się jak można było zrobić to inaczej.

    Opis : generator impulsów prostokątnych z regulowanym współczynnikiem wypełnienia (1-99%), oraz częstotliwością regulowaną w zakresie od ok.100 Hz do 10 kHz.

    PA.0-PA.1 -> 74F139
    PD.0-PD.6 -> 4 wyświetlacze 7 segmentowe
    PB.0-PB.4 -> 4 przyciski i wyjście sygnału na porcie PB.3

    #include <avr/io.h>
    #include <avr/interrupt.h>    
    #include <avr/pgmspace.h>
    #include <util/delay.h> 
            
    const unsigned char TablZnak[11] PROGMEM = {0x3f, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00,};
    unsigned char BUFOR[4] PROGMEM = {10, 10, 10, 10,};
    
    //odczyt trzeba robic funkcja 
    //pgm_read_byte(&(TablZnak[numer]));
    
    unsigned int OKRES = 65535,PWM = 50;
    volatile unsigned char numer = -1, check = 1;
    unsigned float czest = 122;
    
    // volatile, jesli chce zmienna zmieniac w przerwaniu
    //Low Fuse bit 0x64 
    //High Fuse bit 0xDF
    //Extended 0xFF
    
    int main(void) 
    { 
        
       DDRA = 0xFF; // piny portu A jako wyjscia (zalaczanie wyswietlaczy)
       DDRB = 0x00; // piny portu B jako wejscia
       DDRD = 0xFF; // piny portu D jako wyjscia
       
       PORTB = (1 << PB3); // pin 3 portu B jako wyjscie PWM
       
       TCCR0A|=(1 << WGM01);   //ustawianie timera 0 w tryb CTC 
       TCCR1A|=(1 << COM1A0); 
       TCCR0B|=(1 << CS00| 1 << CS01);   //ustawianie timera 0 z preskalerem 64
       TCCR1B|=(1 << CS10| 1 << WGM12);   //ustawianie timera 1 z preskalerem 1, ustawianie timera 1 w tryb CTC 
    
       OCR0A = 400;   //timer 0
       OCR1A = 10000;   
       
        //zezwolenia na przerwania 
       SREG=(1 << 7);  
       TIMSK = (1 << OCIE0A); 
       TIMSK = (1 << OCIE1A);   
       
       PORTA.0 = 0;
       PORTA.1 = 0;
       
       while(1){
    	if(bit_is_clear(PINB,PB4))
    		{
    			if(++PWM == 100) PWM = 99;
    		
    			BUFOR[0] = TablZnak[PWM%10];
    			BUFOR[1] = TablZnak[PWM/10];
    			BUFOR[2] = 0x00;
    			BUFOR[3] = 0x00;
    			
    			_delay_ms(35);
    		}
    		
    		if(bit_is_clear(PINB,PB2))
    		{
    			if(--PWM == 0) PWM = 1;
    			
    			BUFOR[0] = TablZnak[PWM%10];
    			BUFOR[1] = TablZnak[PWM/10];
    			BUFOR[2] = 0x00;
    			BUFOR[3] = 0x00;
    			
    			_delay_ms(35);
    		}
    		
    		if(bit_is_clear(PINB,PB1))
    		{	
    			OKRES = OKRES + 1000;
    			if(OKRES > 65535) OKRES = 65535;	// min czestotliwosc 122 Hz
    			czest=1/(1/(8000000)*OKRES);
    			BUFOR[0] = TablZnak[czest%10];
    			BUFOR[1] = TablZnak[czest/10];
    			BUFOR[2] = TablZnak[czest/100];
    			
    			if(czest<1000) BUFOR[3] = 0x00;
    			else BUFOR[3] = TablZnak[czest/1000];
    			_delay_ms(35);
    		}
    		
    		if(bit_is_clear(PINB,PB0))
    		{
    			OKRES = OKRES - 1000;
    			if(OKRES < 800) OKRES = 800; // max czestotliwosc 10kHz
    			czest=1/(1/(8000000)*OKRES);
    			BUFOR[0] = TablZnak[czest%10];
    			BUFOR[1] = TablZnak[czest/10];
    			BUFOR[2] = TablZnak[czest/100];
    			
    			if(czest<1000) BUFOR[3] = 0x00;
    			else BUFOR[3] = TablZnak[czest/1000];
    			_delay_ms(35);
    		}
       } 
    }
    
    ISR(TIMER0_COMPA_vect) 
    {
    	numer++;
    	PORTD = pgm_read_byte(&(BUFOR[numer]));
    	if (numer == 0)
    		PORTA = 0x0;
    	}
    	if (numer == 1)
    	{
    		PORTA = 0x1;
    	}
    	if (numer == 2)
    	{
    		PORTA = 0x2;
    	}
    	if (numer == 3)
    	{
    		PORTA = 0x4;
    		numer = -1;
    	}
    }
    ISR(TIMER1_COMPA_vect) 
    { 
    	if(check == 1)
    	{
    	OCR1A = OKRES*PWM/100;
    	check++;
    	}
    	else
    	{
    	OCR1A = OKRES*(100-PWM)/100;
    	check = 1;
    	}
    }
    
  • Pomocny post
    #3 7552986
    mario06
    Poziom 15  
    
       ... 
       DDRB = 0x00; // piny portu B jako wejscia
       ...   
       PORTB = (1 << PB3); // pin 3 portu B jako wyjscie PWM
       ... 
    

    to chyba powinno być wyjście, a nie stan wysoki ustalony na pinie PB3
  • #5 7556199
    mario06
    Poziom 15  
    Trochę dokładniej się przyjrzałem kodowi i takie pytanie się nasuwa co do możliwości innego rozwiązania czy nie lepiej byłoby korzystać ze sprzętowego PWM i ustawiać jego częstotliwość i wypełnienie.
  • #6 7556516
    kwartet
    Poziom 11  
    Wstępnie planowałem takie rozwiązanie, ale nie do końca rozumiem jak w takim wypadku przebiegałaby zmiana częstotliwości (tzn. zwyczajnie jak to zrobić). Nie potrzebuję regulacji wypełnienia w zakresie od 1/1024 do 1023/1024, na jaki zakres częstotliwości pozwoliłby tryb pwm?
  • #7 7556867
    mario06
    Poziom 15  
    W dokumentacji do Atiny2313 na stronie 102 jest opisana całość, wtedy przy odpowiednich ustawieniach (dla WGM 8 lub 9) jest możliwość sterowania wypełnieniem oraz częstotliwością.
  • #8 8241300
    kwartet
    Poziom 11  
    Dziękuję za odpowiedzi, problem został rozwiązany. Program można ulepszyć tworząc tablicę, w której zapisane będą odpowiednie częstotliwości, w przypadku tego programu przejścia pomiędzy kolejnymi częstotliwościami nie są zrealizowane na zasadzie 1,10,100,500,1000 Hz (lub podobnej).
REKLAMA