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][UART] brak jednego bitu

iceCocoo 27 Wrz 2009 23:39 1797 7
REKLAMA
  • #1 7065607
    iceCocoo
    Poziom 10  
    Witam,

    Problem polega na tym, że po przesłaniu bajtu informacji ( nie zależnie od długości ), zawsze brakuje pierwszego bitu. Sprawdziłem to po przez ustawienie odpowiednio zapalenia lub mrygania na wartość bitu 0 lub 1.
    Sprawdzając najpierw wiadomości 8 bitowe, a później schodząc w dół, doszedłem do wniosku, że bity są ustawione nie jak by się przypuszczało (np. 0xf0 = 1111 0000, 0x57 = 0101 0111) a w sposób miejscowy (np. dwa to zawsze dwa pierwsze bity zero, 5 to pierwszy i przed ostatni). Wybierając przypadkowe numery stwierdziłem, że niektóre kombinacje się powtarzają i że pierwszym bitem jest zawsze zero. Tak chyba nie powinno być, prawda?

    Komunikowałem się z uC za pomocą Pythona (PySerial) i HyperTerminal Private Edition (mam Vistę).

    W kodzie jest ustawione na 5 bitów, ale to tylko dlatego, żeby dokładniej sprawdzić czy rzeczywiście nie ma jednego bitu na wszystkich bajtach.

    kod uC:

    #define F_CPU           (1000000ul)    // Hz
    #define UART_BAUD       (2400ul)       // BAUD
    
    #include <avr/io.h>             
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdint.h>
    
    
    #define LED_DDR			DDRB
    #define LED_PORT        PORTB      
    #define LED_BIT			0x01
    
    #define LED_ON  (LED_PORT = LED_BIT)
    #define LED_OFF (LED_PORT = 0x00)
    
    #define UBRR	((F_CPU/16ul/UART_BAUD)-1)
    
    
    ///////////////////////////////////////////////////////
    // PRE_FUNCTIONS
    uint16_t USART_receive(void);
    void init(void);
    void led_flashing(uint16_t);
    
    void start_signal(void);
    void command_signal(uint16_t);
    
    uint8_t readByte(void);
    
    ................
    
    //////////////////////////////////////////////////////////////////
    // INITIALIZATION 
    void init(void){	
    	LED_DDR = LED_BIT;
    	LED_OFF;
    }
    
    void USART_init(void)
    {
    	// set UBRR / speed
    	UBRRH = (UBRR >> 8);
    	UBRRL = UBRR;
    	
    	// clearing all errors
    	UCSRA &= ~( (1<<FE) | (1<<DOR) );
    
    	// enable Receive&Transmitt
    	UCSRB |= ( (1<<RXEN) | (1<<TXEN) );
    
    	// 5 bits, 1stop, Failing XCK Edge
    	UCSRC |= ( (1<<URSEL) | (0<<UCSZ1) | (0<<UCSZ0) | (1<<UCPOL) );	
    
    	UDR = 0;
    }
    
    ///////////////////////////////////////////////////////
    // MAIN
    int main(void)                        
    {
      uint16_t command;
      init();			
      USART_init();
     
      while(1)
      {
      	// wait for command
    	command = USART_receive();	
    
    	command_signal( command );
    
    	_delay_ms(240); 
      }
    
      return 0;
    }
    
    ///////////////////////////////////////////////////////
    // FUNCTIONS
    uint16_t USART_receive(void)
    {
           uint8_t  most, least;
           uint16_t data;
    
           most  = readByte();
           least = readByte();
    
           data = most;
           data = ( data << 5 );
           data|= (uint16_t)least;
    
           return data;
    }
    
    
    uint8_t readByte(void)
    {
    while (!(UCSRA & (1<<RXC)));
    c = UDR;
    		
    return c;
    }
    
    
    void command_signal(uint16_t data)
    {
    	uint8_t i=10;
    	while(i)
    	{
    		if(data &(1<<9)) 
    		{	
    			asm("nop");
    			logic_1();
    		}
    		else logic_0();
    		data <<= 1;
    		--i;
    	}
    }
    
    ......................
    
  • REKLAMA
  • #2 7065709
    BoskiDialer
    Poziom 34  
    Zastanów się, czy inicjalizacja z użyciem "|=" jest poprawna. UCSRC i UBRRH w tym procesorze współdzielą adres. Zgodnie z notą pierwszy odczyt UCSRC w rzeczywistości zwróci UBRRH, tak więc
    UCSRC |= ( (1<<URSEL) | (0<<UCSZ1) | (0<<UCSZ0) | (1<<UCPOL) );  

    można inaczej zapisać jako:
    UCSRC = UBRRH | ( (1<<URSEL) | (0<<UCSZ1) | (0<<UCSZ0) | (1<<UCPOL) );

    Nie jest to poprawne, chociaż nie spowoduje znaczących problemów ze względu na prędkość, która powoduje, że UBRRH będzie równy 0.

    Kolejna rzecz - flag błędów odbioru nie skasujesz w ten sposób. Te flagi są skojarzone z odebranym bajtem, więc aby skasować flagi należy odczytać UDR (nawet jeśli dane są uszkodzone).

    Czytając o mieszaniu się bitów odnoszę wrażenie, że przekombinowałeś. Nadajnik i odbiornik muszą pracować z tą samą liczbą bitów. Jeśli nadajnik wysyła 8 bitów - 0x57, to przebieg będzie postaci xx0 1110 1010 1xx gdzie xx0 to stan początkowy + bit stopu, dalej są bity w kolejności od LSB, potem 1xx to bit stopu. Odbiornik pracujący przy 5 bitach źle rozbije ramkę a dokładniej to wystąpi błąd ramki, gdyż bit stopu jest niepoprawny.

    Jeśli piszesz o UART'cie to pewnie masz na myśli transmisję asynchroniczną. W takim przypadku wejście XCK nie jest wykorzystywane przez U(S)ART.
  • REKLAMA
  • #3 7065738
    iceCocoo
    Poziom 10  
    To zerowanie bitów błędu dodałem już po tym jak stwierdziłem, że nie działa. W końcu nigdy nie zaszkodzi spróbować ;)

    Najwyraźniej, tak jak zauważyłeś, jest problem z tą ramką. Jednakże, pierwszy raz mam do czynienia z taką niską komunikacją i nie mam pojęcia jak to naprawić.
    W ustawieniach klientów zaznaczałem zawsze zgodnie z przeznaczeniem (baud 2400, x bitów). Czy powinienem dodawać jakieś sprawdzenia parzystości albo zwiększyć liczbę stopów?
    W jaki sposób obsłużyć, o ile to jest problemem, błąd ramkowania?
  • #4 7066409
    szelus
    Poziom 34  
    A jakiego zegara wogóle używasz? Kwarc, czy wewnętrzny RC?
    Pierwszy bit to który, najstarszy, dobrze zrozumiałem?

    Bo dla mnie, to wygląda tak, jakby po prostu zegary (prędkości) się nie zgadzały. Zwłaszcza, że nie sprawdzasz, czy był błąd transmisji (ramki).
    Fuse-y poprawnie ustawione (zgodnie z założonym zegarem)?
  • REKLAMA
  • #5 7066575
    iceCocoo
    Poziom 10  
    Używam wewnętrznego RC i jak czytałem to jest 1MHz. Nie napisałem potwierdzenie, ponieważ myślałem, że jest nie potrzebne. Muszę to zrobić? Bardzo to pomoże?
    Jakie powinienem kroki zrobić, żeby pomogło?
  • REKLAMA
  • #6 7069315
    Konto nie istnieje
    Poziom 1  
  • #7 7069657
    _Robak_
    Poziom 33  
    Jesli nie zewnetrzny kwarc, to przynajmniej sprobuj wykalibrowac RC rejestrem OSCCAL.
  • #8 7072358
    Konto nie istnieje
    Poziom 1  
REKLAMA