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

[atmega8] [c] [avrstudio] + enkoder

jerraz 07 Wrz 2009 11:57 2666 6
REKLAMA
  • #1 6990077
    jerraz
    Poziom 10  
    Witam serdecznie, potrzebuje pomocy w napisaniu programu dla atmega8.

    Chodzi mi o pomoc w jego napisaniu. Z programowania nie jestem najlepszy. Problem polega na:Sczytaniu wartości z przetwornika (http://www.wobit.com.pl/download/pdf/przetworniki/MAK50.pdf), konwersji z kodu Gray`a na kod binarny oraz przesłaniu za pomocą rs232 na PC. Wszystko to na przerwaniach.

    Co do samego sczytania wartości to wiem,że przetwornik jest enkoderem 10-bitowym. Postanowiłem, że wykorzystam port C i D uC. Do portu C podłącze 6 przewodów (mam wszystkie 6 do dyspozycji), a do portu D 4. Mniej więcej wiem jak tego dokonać. Potrzebuje do tego zmiennej 10-bitowej (16 bitów wystarczy), by "upakować" 6 bit i 4 bit w int.

    cala_liczba = (bity_bardziej_znaczace<<4) | bity_mniej_znaczace;

    Przesuwamy po prostu bity bardziej znaczące o 4 miejsca w lewo, a później dołączamy (operacja or na bitach) bity mniej znaczące. Wcześniej trzeba by skonwertować zmienną z bitami bardziej znaczącymi do long long int tak żeby po przesunięciu o 4 miejsca nie 'przekręciła' się.

    W bardziej ogólnym przypadku gdy każdy z bitów jest w innej zmiennej można napisać:

    wynik=0;

    for (int i=0;i<ilosc_bitow;i++) {

    wynik=wynik<<1;

    wynik=wynik | tablica_bitow[i];

    }

    Kolejno wiem, że mam dokonać konwersji z kodu Gray`a na binarny. Wiem jak tego doknać na kartce papieru, natomast gorzej zaimplementować to w programie. Do tego wszystkiego ma to być dokonane na przerwanaich,których zupełnie nie rozumiem. Prosze o pomoc. pozdrawiam
  • REKLAMA
  • #2 6990102
    Freddie Chopin
    Specjalista - Mikrokontrolery
    jerraz napisał:
    Wcześniej trzeba by skonwertować zmienną z bitami bardziej znaczącymi do long long int tak żeby po przesunięciu o 4 miejsca nie 'przekręciła' się.

    Tia, do przesuwania o 4 miejsca faktycznie 64-bity to minimum <: Dobrze że nie long long long long long long double int <:

    4\/3!!
  • REKLAMA
  • #3 6991023
    kwesoly
    Poziom 15  
    Nie róbcie sobie krzywdy z typami int, unsigned int i podobnymi jak to Freddie nazwał longlonglongami.

    #include <intypes.h>

    zawiera:
    uint8_t, int8_t,uint16_t, int16_t, uint32_t, int32_t


    Grzebiąc po internecie wymęczyłem takie coś:
    uint16_t grayToBinary(uint16_t temp)
    {
    	temp ^= (temp>>8);
    	temp ^= (temp>>4);
    	temp ^= (temp>>2);
    	temp ^= (temp>>1);
    	return temp;
    }
    

    Powinno działać ale dopiero wieczorem dam rade to sprawdzić.
  • REKLAMA
  • #5 6993555
    kwesoly
    Poziom 15  
    Dzięki za sugestie - sprawdziłem, funkcja działa w porządku dla liczb 16 bitowych.

    Poniżej konwersja w obie strony i program testowy napisany na szybko.

    #include <stdio.h>
    #include <stdint.h>
    
    uint16_t grayToBinary(uint16_t num)
    {
    	num ^= (num>>8);
    	num ^= (num>>4);
    	num ^= (num>>2);
    	num ^= (num>>1);
    	return num;
    }
    
    uint16_t binaryToGray(uint16_t num)
    {
    	return num^(num>>1);
    }
    
    int main()
    {
    	uint16_t i;
    	for (i = 1; i > 0; ++i) {
    		if(i!=binaryToGray(grayToBinary(i)) || i!=grayToBinary(binaryToGray(i)))
    			printf("blad dla liczby %d",i);
    	}
    	printf("ok");
    return 0;
    }
    
  • #6 6994308
    jerraz
    Poziom 10  
    O dzięki, ale może trochę po kolei. Na samym początku musiałbym zadeklarować porty,które będę używać.

    
    
    #include <avr/io.h>                        // dostęp do rejestrów
    #include <stdint.h>
    #include <stdio.h>
    #include <avr/interrupt.h>              // aby użyć funkcji obsługi przerwań 
    
    
    
    int main( void )                        // program główny
    {
    
    	DDRC = 0x00;	// PortC jako wejście (6 z 10 przewodow enkodera)
       PORTC = 0x00;	// z podciągnięciem do  GND
    	DDRD = 0x4C;	// PortD: PD0 wejscie oraz PD1 jako wyjscia do MAX232; PD2 PD3 PD6 PD7 jako wejscia (brakujace 4 przewody do enkodera)	
    	
                                                                
     while(1)                                // pętla nieskończona
     {
    
    uint16_t grayToBinary(uint16_t num) 
    { 
       num ^= (num>>8); 
       num ^= (num>>4); 
       num ^= (num>>2); 
       num ^= (num>>1); 
       return num; 
    } 
    
    uint16_t binaryToGray(uint16_t num) 
    { 
       return num^(num>>1); 
    } 
    
    int main() 
    { 
       uint16_t i; 
       for (i = 1; i > 0; ++i) { 
          if(i!=binaryToGray(grayToBinary(i)) || i!=grayToBinary(binaryToGray(i))) 
             printf("blad dla liczby %d",i); 
       } 
       printf("ok");
    
     }
    
    }
    
    
    


    Ma być do wykonywane na przerwaniach... ma ktoś pomysł?
    Z góry dzięki.
    P.S.
    Tak wygląda połączenie:
    [atmega8] [c] [avrstudio] + enkoder[/url]
  • REKLAMA
  • #7 7004490
    jerraz
    Poziom 10  
    Witam serdecznie,
    program ewoluował i w chwili obecnej przyjmuje postać:

    
    #include <avr/io.h>             // dostęp do rejestrów
    #include <stdint.h>
    #include <stdio.h>
    #include <avr/interrupt.h>      // aby użyć funkcji obsługi przerwań 
    //przerwanie od INT0
    SIGNAL (SIG_INTERRUPT0) 	//obsługa przerwania
    {
    uint16_t GrayToBinary(uint16_t gray) //
    }
    //przerwanie od USART
    uint16_t GrayToBinary(uint16_t gray)  // funkcja przliczajaca z kodu gray`a na NKB
    {                                     
       uint16_t binary;
       binary = (gray & (2^9));                     //przepisujemy najstarszy bit, pozostale 0 ` (gray & 1000...00)
       binary |= (( gray ^ (binary>>1) )  &(2^8) )  //wyliczamy 2-gi najstarszy bit, pozostale zerujemy poprzez operacje &(2^8) czyli & 0100000000
       binary |= (( gray ^ (binary>>2) )  &(2^7) )   //wyliczamy kolejne bity
       binary |= (( gray ^ (binary>>3) )  &(2^6) )
       binary |= (( gray ^ (binary>>4) )  &(2^5) )
       binary |= (( gray ^ (binary>>5) )  &(2^4) )
       binary |= (( gray ^ (binary>>6) )  &(2^3) )
       binary |= (( gray ^ (binary>>7) )  &(2^2) )
       binary |= (( gray ^ (binary>>8) )  &(2^1) )
       binary |= (( gray ^ (binary>>9) )  &(2^0) )  //wyliczamy najmłodszy bit &0000000001
      return binary; 
    } 
    void Inicjalizacja(void)
    {
       DDRC  = 0x00;        // PortC jako wejścia (6 z 10 przewodow enkodera) 
       PORTC = 0x00;        //z podciąganiem do  VCC , 
       DDRD  = 0x00;        // PortD:  PD2 PD3 PD4 PD5 jako wejscia (brakujace 4 przewody do enkodera), 
    }
    int main(void)
    uint16_t bity_bardziej_znaczace, cala_liczba, do_wyslania;
    uint8_t bity_mniej_znaczace, semafor, znak;  			
    {
    Inicjalizacja(); 	// Wywołanie funkcji inicjującej uzyte porty
    PORTC & 0x20;     	// Testuj bit 2 portu C.
    GIMSK = _BV(INT0); 	//Włączenie przerwania
    MCUCR = (MCUCR & (~(3<<ISC00))) | (1<<ISC00); PRZERWANIE WYKONYWANE NA OBU ZBOCZACH
    sei(); 			//Włączenie obsługi przerwań
    while(1) 		// Rozpoczęcie pętli głównej
    {
       program bedzie cały czas wykonywał pętl główną
     if (semafor=1)
      {
       bity_mniej_znaczace= (PORD&0b00111100) >>2; //   bierzemy PD2-PD4 a pozostale zerujemy   i przesuwamy o 2 bity w prawo
       bity_bardziej_znaczace=(PORTC&0b00111111);  //zerujemy na wszelki wypadek niewykorzystane bity
       cala_liczba = (bity_bardziej_znaczace<<4) | bity_mniej_znaczace;  
       do_wyslania = GrayToBinary(cala_liczba);  
       semafor=0;
      }
    }
    return 0; 
    }
    
REKLAMA