Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

AT90s2313 a rejestry przesuwające - jak to połączyć ?

xPatryk 06 Jan 2005 00:05 1560 12
  • #1
    xPatryk
    Level 15  
    No właśnie...
    mam układ złożony z rejestrów przesównych (ma on na zadanie włączać określone urządzenia, nie jest tu istotny czas reakcji itp...)

    chodzi mi o to, jak to coś (schemat poniżej) podłączyć do procka AT90s2313

    Pozdrawiam i proszę o pomoc

    Patryk
  • #2
    Zbych_
    Level 25  
    2313 nie ma żadnego sprzętowego mechanizmu wspomagającego transmisję synchroniczną, więc możesz ten układ podłączyć do dowolnych portów, bo i tak całą transmisję będziesz musiał zrobić w sposób programowy.
  • #3
    xPatryk
    Level 15  
    yy... a jak to mniej/więcej wysterować np. pod Bascom'em lub C ?
  • #4
    elektryk
    Level 42  
    xPatryk wrote:
    yy... a jak to mniej/więcej wysterować np. pod Bascom'em lub C ?
    Programowo zmieniasz stan każdego pinu, tak aby wygenerować sygnał zegara i danych.
  • #5
    GienekS
    Level 32  
    Jeżeli znasz dzałenie tej kostki (4094) to robisz to tak:
    1. Na wejście podajesz kolejne bity danych
    2. Zmienisz stan lini zegara na 0
    3. Zmienisz stan lini zegara na 1
    4. Powtarzasz punkty od 1. do 3. tyle razy ile bitów chcesz przesłać
    5. Zmieniasz stan lini Strob na 0
    6. Zmieniasz stan lini Strob na 1
    i finał sprawy, na wyjściu rejestrów masz stany tych bitów które podawałeś w punkcie 1. Czy to jasne ?
  • #6
    robkry
    Level 15  
    Podaję prosty przykład dla AVR-GCC:
    
    #include <avr/io.h>
    
    /* Oblicza ddres rejestru kierunkowego na podstawie rejestru wyjściowego PORTx.*/
    #define DDR(x) _SFR_IO8(_SFR_IO_ADDR(x)-1)
    
    #define REG_CLK_PORT	PORTD	// port, do którego jest podłączone wejście zegarowe rejestru
    #define REG_CLK_BIT	5	// bit powyższego portu
    
    #define REG_DAT_PORT	PORTD	// port, do którego jest podłączone wejście danych rejestru
    #define REG_DAT_BIT	4	// bit powyższego portu
    
    #define REG_STB_PORT	PORTD	// port, do którego jest podłączone wejście strobujące rejestru
    #define REG_STB_BIT	3	// bit powyższego portu
    
    /* Wysyła 16 bitów ze zmiennej zn na rejestr przesówny i zatrzaskuje go */
    void REG_out (int16_t zn)
    {
      int16_t n;
      for(n=15; n>=0; n--) 		 // będziemy sprawdzać wszyskie bity zmiennej
      {
        if (((zn >> n) & 1) == 0) 		// jezeli wartosc bitu wynosi 0 
          cbi(REG_DAT_PORT,REG_DAT_BIT);    // to wpisz 0 na wej. rejestru przes
        else
          sbi(REG_DAT_PORT,REG_DAT_BIT);    // w przeciwnym wypadku 1
        sbi(REG_CLK_PORT,REG_CLK_BIT);   // imp CLK na 1
        cbi(REG_CLK_PORT,REG_CLK_BIT);   // imp CLK na 0
      }
      sbi(REG_STB_PORT,REG_STB_BIT);   // imp STB na 1
      cbi(REG_STB_PORT,REG_STB_BIT);   // imp STB na 0
    }
    
    int main(void)
    {                
    /* ustawiamy CLK, DAT i STB jako wyjścia */
      sbi(DDR(REG_CLK_PORT),REG_CLK_BIT);
      sbi(DDR(REG_DAT_PORT),REG_DAT_BIT);
      sbi(DDR(REG_STB_PORT),REG_STB_BIT);
    
    /* wystawiamy na przemian 0/1 */
      REG_out(0x5555);  
    
    /* pętla nieskończona */
      while(1);
    }
    


    Przypisując odpowiednie definicje do makr
    #define REG_CLK_PORT
    #define REG_CLK_BIT
    #define REG_DAT_PORT
    #define REG_DAT_BIT
    #define REG_STB_PORT
    #define REG_STB_BIT
    możesz dostosować kod do swoich potrzeb.
    Do wysyłania danych służy funkcja REG_out(dana).

    Pozdrawiam.
  • #7
    mzielin
    Level 22  
    Basic FastAVR ma bibliotekę z funkcją realizującą to wpisywanie. Trzeba zadbać tylko o STROBE.
  • #8
    Zbych_
    Level 25  
    robkry wrote:
    Podaję prosty przykład dla AVR-GCC:
    
    void REG_out (int16_t zn)
    {
      int16_t n;
      for(n=15; n>=0; n--) 		 // będziemy sprawdzać wszyskie bity zmiennej
      {
        if (((zn >> n) & 1) == 0) 		// jezeli wartosc bitu wynosi 0 
          cbi(REG_DAT_PORT,REG_DAT_BIT);    // to wpisz 0 na wej. rejestru przes
        else
          sbi(REG_DAT_PORT,REG_DAT_BIT);    // w przeciwnym wypadku 1
        sbi(REG_CLK_PORT,REG_CLK_BIT);   // imp CLK na 1
        cbi(REG_CLK_PORT,REG_CLK_BIT);   // imp CLK na 0
      }
      sbi(REG_STB_PORT,REG_STB_BIT);   // imp STB na 1
      cbi(REG_STB_PORT,REG_STB_BIT);   // imp STB na 0
    }
    


    Wybrałeś bardzo nieefektywny sposób wyłuskiwania bitu z liczby. W każdym obiegu pętli musi być obliczana pozycja bitu (n >> n)&1.
    Proponowałbym przesuwanie w każdym obiegu pętli tylko o jeden bit i korzystanie zawsze z najstarszego (lub najmłodszego, w zależności od kierunku) bitu.
    
    void REG_out (int16_t zn)
    {
    uint8_t licznik;
    
      licznik=16;
      do{
        if ((zn & 0x8000) == 0)
          cbi(REG_DAT_PORT,REG_DAT_BIT);    
        else
          sbi(REG_DAT_PORT,REG_DAT_BIT); 
        sbi(REG_CLK_PORT,REG_CLK_BIT);
        cbi(REG_CLK_PORT,REG_CLK_BIT);
        zn<<=1;
      }while(--licznik!=0);
    
      sbi(REG_STB_PORT,REG_STB_BIT);
      cbi(REG_STB_PORT,REG_STB_BIT);
    }
    


    Tak zbudowana pętla wykonuje się kilkukrotnie szybciej i zajmuje mniej pamięci programu.

    Pozdrawiam
  • #9
    robkry
    Level 15  
    @Zbych_ Prawda. Tak jest znacznie lepiej. Dziękuję za podpowiedź. Tamten kod wyłuskałem z jakiś starych archiwów i go zaadaptowałem do AVR - dotyczył programowania na PC nik się w optymalizacje nie bawił - a powinien.

    Dziękuję i pozdrawiam.
  • #10
    xPatryk
    Level 15  
    Witam,

    próbowałem zrobić, tak, jak pisał GienekS,
    wyszlo mi cos takiego:

    For I = 8 To 1
    If Stan(i) = 1 Then Portb.1 = 1
    If Stan(i) = 0 Then Portb.1 = 0
    Portb.2 = 0
    Portb.2 = 1
    Next I
    Portb.0 = 0
    Portb.0 = 1


    w tablicy Stan(i) przechowuje wartosci 1 lub 0, w zaleznosci, czy urzadzenie jest wlaczone.

    do PB.0 podlczylem wejscie strobujece, PB.2 - wejscie zegarowe a PB.1 - wejscie danych...

    niestety, calosc konczy sie na tym, ze po restarcie przemiata jeden raz wszystkie wyjscia i nic :(

    uzywam ukladu CD4097BE...

    Proszę o pomoc.
  • #11
    zumek
    Level 39  
    xPatryk wrote:
    w tablicy Stan(i) przechowuje wartosci 1 lub 0, w zaleznosci, czy urzadzenie jest wlaczone.

    Marnotrawstwo i tak już skąpego RAM-u.
    xPatryk wrote:
    
    For I=8 To 1
    ...
    ...
    Next I
    

    Ta petla , nigdy się nie wykona :(
    Użyj bitów do zapamiętywania stanów i dyrektywy STEP dla For.

    Piotrek
  • #12
    xPatryk
    Level 15  
    ajj.. masz racje ;)

    ale przy pomocy bitow nie stworze tablicy, wiec kazdy musialbym osobno przypisac, nie?
  • #13
    zumek
    Level 39  
    xPatryk wrote:

    ale przy pomocy bitow nie stworze tablicy, wiec kazdy musialbym osobno przypisac, nie?


    To tylko tak Ci się wydaje :wink:
    Przykładzik:
    
    dim tab as word      'robi za 16-to bitową tablicę bitów.
    declare sub wyslij(byval buf as word)
    bit15 alias 15
    bit14 alias 14
    ...
    Patelnia alias 0      'bity ponazywaj jak chcesz
    
    'zakładem , że bit ustawiony to włącz , a wyzerowany wyłącz
    tab=0       'wszystko ma być wyłączone
    ...
    call wyslij(tab) 
    ...
    set tab.patelnia   'włącz patelmnię i ...
    set.bit15             'urządzanie nr.15
    
    call wyslij(tab) 
    
    
    Sub Wyslij(byval Buf As Word)
    Local I As Byte
    For I = 15 To 0 Step -1
       Portb.1 = Buf.i
       Portb.2 = 0
       Portb.2 = 1
    Next I
    Portb.0 = 0
    Portb.0 = 1
    End Sub
    


    Piotrek